Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 08/12] net: hns3: optimize waiting time for TQP reset
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Zhongzhu Liu, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Zhongzhu Liu <liuzhongzhu@huawei.com>

This patch optimizes the waiting time for TQP reset.

Signed-off-by: Zhongzhu Liu <liuzhongzhu@huawei.com>
Reviewed-by: Yunsheng Lin <linyunsheng@huawei.com>
Reviewed-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 ++++++----
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 8a5b81d..f43c298 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -8262,11 +8262,12 @@ int hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
 	}
 
 	while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) {
-		/* Wait for tqp hw reset */
-		msleep(20);
 		reset_status = hclge_get_reset_status(hdev, queue_gid);
 		if (reset_status)
 			break;
+
+		/* Wait for tqp hw reset */
+		usleep_range(1000, 1200);
 	}
 
 	if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) {
@@ -8300,11 +8301,12 @@ void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id)
 	}
 
 	while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) {
-		/* Wait for tqp hw reset */
-		msleep(20);
 		reset_status = hclge_get_reset_status(hdev, queue_gid);
 		if (reset_status)
 			break;
+
+		/* Wait for tqp hw reset */
+		usleep_range(1000, 1200);
 	}
 
 	if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 7ff03b9..00c07f8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -119,7 +119,7 @@
 #define HCLGE_DEFAULT_UMV_SPACE_PER_PF \
 	(HCLGE_UMV_TBL_SIZE / HCLGE_MAX_PF_NUM)
 
-#define HCLGE_TQP_RESET_TRY_TIMES	10
+#define HCLGE_TQP_RESET_TRY_TIMES	200
 
 #define HCLGE_PHY_PAGE_MDIX		0
 #define HCLGE_PHY_PAGE_COPPER		0
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 09/12] net: hns3: implement .process_hw_error for hns3 client
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Weihang Li, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Weihang Li <liweihang@hisilicon.com>

When hardware or IMP get specified error it may need the client
to take some special operations.

This patch implements the hns3 client's process_hw_errorx.

Signed-off-by: Weihang Li <liweihang@hisilicon.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Reviewed-by: Peng Li <lipeng321@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hnae3.h        |  9 +++++-
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.c    | 24 ++++++++++++++++
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.h    |  5 ++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c |  4 ++-
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h |  1 +
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 33 ++++++++++++++++++++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h    |  4 +++
 7 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 3e21533..c4b7bf8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -146,6 +146,12 @@ enum hnae3_reset_notify_type {
 	HNAE3_RESTORE_CLIENT,
 };
 
+enum hnae3_hw_error_type {
+	HNAE3_PPU_POISON_ERROR,
+	HNAE3_CMDQ_ECC_ERROR,
+	HNAE3_IMP_RD_POISON_ERROR,
+};
+
 enum hnae3_reset_type {
 	HNAE3_VF_RESET,
 	HNAE3_VF_FUNC_RESET,
@@ -210,7 +216,8 @@ struct hnae3_client_ops {
 	int (*setup_tc)(struct hnae3_handle *handle, u8 tc);
 	int (*reset_notify)(struct hnae3_handle *handle,
 			    enum hnae3_reset_notify_type type);
-	enum hnae3_reset_type (*process_hw_error)(struct hnae3_handle *handle);
+	void (*process_hw_error)(struct hnae3_handle *handle,
+				 enum hnae3_hw_error_type);
 };
 
 #define HNAE3_CLIENT_NAME_LENGTH 16
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index a11d514..9f3f8e3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -4470,12 +4470,36 @@ int hns3_set_channels(struct net_device *netdev,
 	return hns3_reset_notify(h, HNAE3_UP_CLIENT);
 }
 
+static const struct hns3_hw_error_info hns3_hw_err[] = {
+	{ .type = HNAE3_PPU_POISON_ERROR,
+	  .msg = "PPU poison" },
+	{ .type = HNAE3_CMDQ_ECC_ERROR,
+	  .msg = "IMP CMDQ error" },
+	{ .type = HNAE3_IMP_RD_POISON_ERROR,
+	  .msg = "IMP RD poison" },
+};
+
+static void hns3_process_hw_error(struct hnae3_handle *handle,
+				  enum hnae3_hw_error_type type)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hns3_hw_err); i++) {
+		if (hns3_hw_err[i].type == type) {
+			dev_err(&handle->pdev->dev, "Detected %s!\n",
+				hns3_hw_err[i].msg);
+			break;
+		}
+	}
+}
+
 static const struct hnae3_client_ops client_ops = {
 	.init_instance = hns3_client_init,
 	.uninit_instance = hns3_client_uninit,
 	.link_status_change = hns3_link_status_change,
 	.setup_tc = hns3_client_setup_tc,
 	.reset_notify = hns3_reset_notify,
+	.process_hw_error = hns3_process_hw_error,
 };
 
 /* hns3_init_module - Driver registration routine
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index e37e64e..2110fa3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -552,6 +552,11 @@ union l4_hdr_info {
 	unsigned char *hdr;
 };
 
+struct hns3_hw_error_info {
+	enum hnae3_hw_error_type type;
+	const char *msg;
+};
+
 static inline int ring_space(struct hns3_enet_ring *ring)
 {
 	/* This smp_load_acquire() pairs with smp_store_release() in
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
index d986c36..58c6231 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
@@ -1325,10 +1325,12 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev,
 	/* log PPU(RCB) errors */
 	desc_data = (__le32 *)&desc[3];
 	status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_RAS_MASK;
-	if (status)
+	if (status) {
 		hclge_log_error(dev, "PPU_PF_ABNORMAL_INT_ST0",
 				&hclge_ppu_pf_abnormal_int[0], status,
 				&ae_dev->hw_err_reset_req);
+		hclge_report_hw_error(hdev, HNAE3_PPU_POISON_ERROR);
+	}
 
 	/* clear all PF RAS errors */
 	hclge_cmd_reuse_desc(&desc[0], false);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
index 7ea8bb2..876fd81a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
@@ -5,6 +5,7 @@
 #define __HCLGE_ERR_H
 
 #include "hclge_main.h"
+#include "hnae3.h"
 
 #define HCLGE_MPF_RAS_INT_MIN_BD_NUM	10
 #define HCLGE_PF_RAS_INT_MIN_BD_NUM	4
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index f43c298..9ef1f468 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3265,6 +3265,38 @@ static int hclge_func_reset_sync_vf(struct hclge_dev *hdev)
 	return -ETIME;
 }
 
+void hclge_report_hw_error(struct hclge_dev *hdev,
+			   enum hnae3_hw_error_type type)
+{
+	struct hnae3_client *client = hdev->nic_client;
+	u16 i;
+
+	if (!client || !client->ops->process_hw_error ||
+	    !test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state))
+		return;
+
+	for (i = 0; i < hdev->num_vmdq_vport + 1; i++)
+		client->ops->process_hw_error(&hdev->vport[i].nic, type);
+}
+
+static void hclge_handle_imp_error(struct hclge_dev *hdev)
+{
+	u32 reg_val;
+
+	reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG);
+	if (reg_val & BIT(HCLGE_VECTOR0_IMP_RD_POISON_B)) {
+		hclge_report_hw_error(hdev, HNAE3_IMP_RD_POISON_ERROR);
+		reg_val &= ~BIT(HCLGE_VECTOR0_IMP_RD_POISON_B);
+		hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, reg_val);
+	}
+
+	if (reg_val & BIT(HCLGE_VECTOR0_IMP_CMDQ_ERR_B)) {
+		hclge_report_hw_error(hdev, HNAE3_CMDQ_ECC_ERROR);
+		reg_val &= ~BIT(HCLGE_VECTOR0_IMP_CMDQ_ERR_B);
+		hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, reg_val);
+	}
+}
+
 int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id)
 {
 	struct hclge_desc desc;
@@ -3471,6 +3503,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
 		hdev->rst_stats.flr_rst_cnt++;
 		break;
 	case HNAE3_IMP_RESET:
+		hclge_handle_imp_error(hdev);
 		reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG);
 		hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG,
 				BIT(HCLGE_VECTOR0_IMP_RESET_INT_B) | reg_val);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 00c07f8..a3bc382 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -178,6 +178,8 @@ enum HLCGE_PORT_TYPE {
 #define HCLGE_VECTOR0_RX_CMDQ_INT_B	1
 
 #define HCLGE_VECTOR0_IMP_RESET_INT_B	1
+#define HCLGE_VECTOR0_IMP_CMDQ_ERR_B	4U
+#define HCLGE_VECTOR0_IMP_RD_POISON_B	5U
 
 #define HCLGE_MAC_DEFAULT_FRAME \
 	(ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN)
@@ -986,4 +988,6 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
 void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time);
 int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev,
 				struct hclge_desc *desc);
+void hclge_report_hw_error(struct hclge_dev *hdev,
+			   enum hnae3_hw_error_type type);
 #endif
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 04/12] net: hns3: reduce the parameters of some functions
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Guojia Liao, Yufeng Mo, Guangbin Huang, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Guojia Liao <liaoguojia@huawei.com>

This patch simplifies parameters of some functions by deleting
unused parameter.

Signed-off-by: Guojia Liao <liaoguojia@huawei.com>
Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 28 +++++++++++-----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index dde17be..fa85d9e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7342,7 +7342,7 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable)
 }
 
 static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid,
-				    bool is_kill, u16 vlan, u8 qos,
+				    bool is_kill, u16 vlan,
 				    __be16 proto)
 {
 #define HCLGE_MAX_VF_BYTES  16
@@ -7453,7 +7453,7 @@ static int hclge_set_port_vlan_filter(struct hclge_dev *hdev, __be16 proto,
 }
 
 static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
-				    u16 vport_id, u16 vlan_id, u8 qos,
+				    u16 vport_id, u16 vlan_id,
 				    bool is_kill)
 {
 	u16 vport_idx, vport_num = 0;
@@ -7463,7 +7463,7 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
 		return 0;
 
 	ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id,
-				       0, proto);
+				       proto);
 	if (ret) {
 		dev_err(&hdev->pdev->dev,
 			"Set %d vport vlan filter config fail, ret =%d.\n",
@@ -7750,7 +7750,7 @@ static int hclge_add_vport_all_vlan_table(struct hclge_vport *vport)
 		if (!vlan->hd_tbl_status) {
 			ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
 						       vport->vport_id,
-						       vlan->vlan_id, 0, false);
+						       vlan->vlan_id, false);
 			if (ret) {
 				dev_err(&hdev->pdev->dev,
 					"restore vport vlan list failed, ret=%d\n",
@@ -7776,7 +7776,7 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
 				hclge_set_vlan_filter_hw(hdev,
 							 htons(ETH_P_8021Q),
 							 vport->vport_id,
-							 vlan_id, 0,
+							 vlan_id,
 							 true);
 
 			list_del(&vlan->node);
@@ -7796,7 +7796,7 @@ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
 			hclge_set_vlan_filter_hw(hdev,
 						 htons(ETH_P_8021Q),
 						 vport->vport_id,
-						 vlan->vlan_id, 0,
+						 vlan->vlan_id,
 						 true);
 
 		vlan->hd_tbl_status = false;
@@ -7843,7 +7843,7 @@ static void hclge_restore_vlan_table(struct hnae3_handle *handle)
 
 		if (state != HNAE3_PORT_BASE_VLAN_DISABLE) {
 			hclge_set_vlan_filter_hw(hdev, htons(vlan_proto),
-						 vport->vport_id, vlan_id, qos,
+						 vport->vport_id, vlan_id,
 						 false);
 			continue;
 		}
@@ -7853,7 +7853,7 @@ static void hclge_restore_vlan_table(struct hnae3_handle *handle)
 				hclge_set_vlan_filter_hw(hdev,
 							 htons(ETH_P_8021Q),
 							 vport->vport_id,
-							 vlan->vlan_id, 0,
+							 vlan->vlan_id,
 							 false);
 		}
 	}
@@ -7893,12 +7893,12 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport,
 						 htons(new_info->vlan_proto),
 						 vport->vport_id,
 						 new_info->vlan_tag,
-						 new_info->qos, false);
+						 false);
 	}
 
 	ret = hclge_set_vlan_filter_hw(hdev, htons(old_info->vlan_proto),
 				       vport->vport_id, old_info->vlan_tag,
-				       old_info->qos, true);
+				       true);
 	if (ret)
 		return ret;
 
@@ -7925,7 +7925,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
 					       htons(vlan_info->vlan_proto),
 					       vport->vport_id,
 					       vlan_info->vlan_tag,
-					       vlan_info->qos, false);
+					       false);
 		if (ret)
 			return ret;
 
@@ -7934,7 +7934,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
 					       htons(old_vlan_info->vlan_proto),
 					       vport->vport_id,
 					       old_vlan_info->vlan_tag,
-					       old_vlan_info->qos, true);
+					       true);
 		if (ret)
 			return ret;
 
@@ -8055,7 +8055,7 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
 	 */
 	if (handle->port_base_vlan_state == HNAE3_PORT_BASE_VLAN_DISABLE) {
 		ret = hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id,
-					       vlan_id, 0, is_kill);
+					       vlan_id, is_kill);
 		writen_to_tbl = true;
 	}
 
@@ -8091,7 +8091,7 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev)
 		while (vlan_id != VLAN_N_VID) {
 			ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
 						       vport->vport_id, vlan_id,
-						       0, true);
+						       true);
 			if (ret && ret != -EINVAL)
 				return;
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 12/12] net: hns3: not allow SSU loopback while execute ethtool -t dev
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Yufeng Mo, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Yufeng Mo <moyufeng@huawei.com>

The current loopback mode is to add 0x1F to the SMAC address
as the DMAC address and enable the promiscuous mode.
However, if the VF address is the same as the DMAC address,
the loopback test fails.

Loopback can be enabled in three places: SSU, MAC, and serdes.
By default, SSU loopback is enabled, so if the SMAC and the DMAC
are the same, the packets are looped back in the SSU. If SSU loopback
is disabled, packets can reach MAC even if SMAC is the same as DMAC.

Therefore, this patch disables the SSU loopback before the loopback
test. In this way, the SMAC and DMAC can be the same, and the
promiscuous mode does not need to be enabled. And this is not
valid in version 0x20.

This patch also uses a macro to replace 0x1F.

Fixes: c39c4d98dc65 ("net: hns3: Add mac loopback selftest support in hns3 driver")
Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
Reviewed-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c |  9 +++--
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 28 ++++++++++++++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 38 ++++++++++++++++++++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h    |  2 ++
 4 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index e219bb1..c52eccc 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -97,7 +97,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
 		break;
 	}
 
-	if (ret)
+	if (ret || h->pdev->revision >= 0x21)
 		return ret;
 
 	if (en) {
@@ -144,7 +144,10 @@ static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode)
 
 static void hns3_lp_setup_skb(struct sk_buff *skb)
 {
+#define	HNS3_NIC_LB_DST_MAC_ADDR	0x1f
+
 	struct net_device *ndev = skb->dev;
+	struct hnae3_handle *handle;
 	unsigned char *packet;
 	struct ethhdr *ethh;
 	unsigned int i;
@@ -160,7 +163,9 @@ static void hns3_lp_setup_skb(struct sk_buff *skb)
 	 * before the packet reaches mac or serdes, which will defect
 	 * the purpose of mac or serdes selftest.
 	 */
-	ethh->h_dest[5] += 0x1f;
+	handle = hns3_get_handle(ndev);
+	if (handle->pdev->revision == 0x20)
+		ethh->h_dest[5] += HNS3_NIC_LB_DST_MAC_ADDR;
 	eth_zero_addr(ethh->h_source);
 	ethh->h_proto = htons(ETH_P_ARP);
 	skb_reset_mac_header(skb);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 29979be..4821fe0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -223,6 +223,9 @@ enum hclge_opcode_type {
 	HCLGE_OPC_MAC_ETHTYPE_ADD	    = 0x1010,
 	HCLGE_OPC_MAC_ETHTYPE_REMOVE	= 0x1011,
 
+	/* MAC VLAN commands */
+	HCLGE_OPC_MAC_VLAN_SWITCH_PARAM	= 0x1033,
+
 	/* VLAN commands */
 	HCLGE_OPC_VLAN_FILTER_CTRL	    = 0x1100,
 	HCLGE_OPC_VLAN_FILTER_PF_CFG	= 0x1101,
@@ -771,6 +774,31 @@ struct hclge_vlan_filter_vf_cfg_cmd {
 	u8  vf_bitmap[16];
 };
 
+#define HCLGE_SWITCH_ANTI_SPOOF_B	0U
+#define HCLGE_SWITCH_ALW_LPBK_B		1U
+#define HCLGE_SWITCH_ALW_LCL_LPBK_B	2U
+#define HCLGE_SWITCH_ALW_DST_OVRD_B	3U
+#define HCLGE_SWITCH_NO_MASK		0x0
+#define HCLGE_SWITCH_ANTI_SPOOF_MASK	0xFE
+#define HCLGE_SWITCH_ALW_LPBK_MASK	0xFD
+#define HCLGE_SWITCH_ALW_LCL_LPBK_MASK	0xFB
+#define HCLGE_SWITCH_LW_DST_OVRD_MASK	0xF7
+
+struct hclge_mac_vlan_switch_cmd {
+	u8 roce_sel;
+	u8 rsv1[3];
+	__le32 func_id;
+	u8 switch_param;
+	u8 rsv2[3];
+	u8 param_mask;
+	u8 rsv3[11];
+};
+
+enum hclge_mac_vlan_cfg_sel {
+	HCLGE_MAC_VLAN_NIC_SEL = 0,
+	HCLGE_MAC_VLAN_ROCE_SEL,
+};
+
 #define HCLGE_ACCEPT_TAG1_B		0
 #define HCLGE_ACCEPT_UNTAG1_B		1
 #define HCLGE_PORT_INS_TAG1_EN_B	2
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index dc22b84..ce4b228 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -6211,6 +6211,30 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
 			"mac enable fail, ret =%d.\n", ret);
 }
 
+static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid,
+				     u8 switch_param, u8 param_mask)
+{
+	struct hclge_mac_vlan_switch_cmd *req;
+	struct hclge_desc desc;
+	u32 func_id;
+	int ret;
+
+	func_id = hclge_get_port_number(HOST_PORT, 0, vfid, 0);
+	req = (struct hclge_mac_vlan_switch_cmd *)desc.data;
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_SWITCH_PARAM,
+				   false);
+	req->roce_sel = HCLGE_MAC_VLAN_NIC_SEL;
+	req->func_id = cpu_to_le32(func_id);
+	req->switch_param = switch_param;
+	req->param_mask = param_mask;
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"set mac vlan switch parameter fail, ret = %d\n", ret);
+	return ret;
+}
+
 static void hclge_phy_link_status_wait(struct hclge_dev *hdev,
 				       int link_ret)
 {
@@ -6465,6 +6489,20 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
 	struct hclge_dev *hdev = vport->back;
 	int i, ret;
 
+	/* Loopback can be enabled in three places: SSU, MAC, and serdes. By
+	 * default, SSU loopback is enabled, so if the SMAC and the DMAC are
+	 * the same, the packets are looped back in the SSU. If SSU loopback
+	 * is disabled, packets can reach MAC even if SMAC is the same as DMAC.
+	 */
+	if (hdev->pdev->revision >= 0x21) {
+		u8 switch_param = en ? 0 : BIT(HCLGE_SWITCH_ALW_LPBK_B);
+
+		ret = hclge_config_switch_param(hdev, PF_VPORT_ID, switch_param,
+						HCLGE_SWITCH_ALW_LPBK_MASK);
+		if (ret)
+			return ret;
+	}
+
 	switch (loop_mode) {
 	case HNAE3_LOOP_APP:
 		ret = hclge_set_app_loopback(hdev, en);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 437a9ff..870550f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -148,6 +148,8 @@ enum HLCGE_PORT_TYPE {
 	NETWORK_PORT
 };
 
+#define PF_VPORT_ID			0
+
 #define HCLGE_PF_ID_S			0
 #define HCLGE_PF_ID_M			GENMASK(2, 0)
 #define HCLGE_VF_ID_S			3
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 05/12] net: hns3: optimize some log printings
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Yufeng Mo, Zhongzhu Liu, Guangbin Huang, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Yufeng Mo <moyufeng@huawei.com>

To better identify abnormal conditions, this patch modifies or
adds some logs to show driver status more accurately.

Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
Signed-off-by: Zhongzhu Liu <liuzhongzhu@huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 25 +++++++++--------
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 32 +++++++++++-----------
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    |  2 +-
 3 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 7070d25..5cf4c1e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -39,7 +39,7 @@ static int hns3_dbg_queue_info(struct hnae3_handle *h,
 
 	if (queue_num >= h->kinfo.num_tqps) {
 		dev_err(&h->pdev->dev,
-			"Queue number(%u) is out of range(%u)\n", queue_num,
+			"Queue number(%u) is out of range(0-%u)\n", queue_num,
 			h->kinfo.num_tqps - 1);
 		return -EINVAL;
 	}
@@ -177,7 +177,7 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
 	}
 
 	if (q_num >= h->kinfo.num_tqps) {
-		dev_err(dev, "Queue number(%u) is out of range(%u)\n", q_num,
+		dev_err(dev, "Queue number(%u) is out of range(0-%u)\n", q_num,
 			h->kinfo.num_tqps - 1);
 		return -EINVAL;
 	}
@@ -188,14 +188,14 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
 	tx_index = (cnt == 1) ? value : tx_index;
 
 	if (tx_index >= ring->desc_num) {
-		dev_err(dev, "bd index (%u) is out of range(%u)\n", tx_index,
+		dev_err(dev, "bd index(%u) is out of range(0-%u)\n", tx_index,
 			ring->desc_num - 1);
 		return -EINVAL;
 	}
 
 	tx_desc = &ring->desc[tx_index];
 	dev_info(dev, "TX Queue Num: %u, BD Index: %u\n", q_num, tx_index);
-	dev_info(dev, "(TX) addr: 0x%llx\n", tx_desc->addr);
+	dev_info(dev, "(TX)addr: 0x%llx\n", tx_desc->addr);
 	dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.vlan_tag);
 	dev_info(dev, "(TX)send_size: %u\n", tx_desc->tx.send_size);
 	dev_info(dev, "(TX)vlan_tso: %u\n", tx_desc->tx.type_cs_vlan_tso);
@@ -219,6 +219,7 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
 
 	dev_info(dev, "RX Queue Num: %u, BD Index: %u\n", q_num, rx_index);
 	dev_info(dev, "(RX)addr: 0x%llx\n", rx_desc->addr);
+	dev_info(dev, "(RX)l234_info: %u\n", rx_desc->rx.l234_info);
 	dev_info(dev, "(RX)pkt_len: %u\n", rx_desc->rx.pkt_len);
 	dev_info(dev, "(RX)size: %u\n", rx_desc->rx.size);
 	dev_info(dev, "(RX)rss_hash: %u\n", rx_desc->rx.rss_hash);
@@ -238,16 +239,16 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	char printf_buf[HNS3_DBG_BUF_LEN];
 
 	dev_info(&h->pdev->dev, "available commands\n");
-	dev_info(&h->pdev->dev, "queue info [number]\n");
+	dev_info(&h->pdev->dev, "queue info <number>\n");
 	dev_info(&h->pdev->dev, "queue map\n");
-	dev_info(&h->pdev->dev, "bd info [q_num] <bd index>\n");
+	dev_info(&h->pdev->dev, "bd info <q_num> <bd index>\n");
 
 	if (!hns3_is_phys_func(h->pdev))
 		return;
 
 	dev_info(&h->pdev->dev, "dump fd tcam\n");
 	dev_info(&h->pdev->dev, "dump tc\n");
-	dev_info(&h->pdev->dev, "dump tm map [q_num]\n");
+	dev_info(&h->pdev->dev, "dump tm map <q_num>\n");
 	dev_info(&h->pdev->dev, "dump tm\n");
 	dev_info(&h->pdev->dev, "dump qos pause cfg\n");
 	dev_info(&h->pdev->dev, "dump qos pri map\n");
@@ -259,20 +260,20 @@ static void hns3_dbg_help(struct hnae3_handle *h)
 	dev_info(&h->pdev->dev, "dump mac tnl status\n");
 
 	memset(printf_buf, 0, HNS3_DBG_BUF_LEN);
-	strncat(printf_buf, "dump reg [[bios common] [ssu <prt_id>]",
+	strncat(printf_buf, "dump reg [[bios common] [ssu <port_id>]",
 		HNS3_DBG_BUF_LEN - 1);
 	strncat(printf_buf + strlen(printf_buf),
-		" [igu egu <prt_id>] [rpu <tc_queue_num>]",
+		" [igu egu <port_id>] [rpu <tc_queue_num>]",
 		HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1);
 	strncat(printf_buf + strlen(printf_buf),
-		" [rtc] [ppp] [rcb] [tqp <q_num>]]\n",
+		" [rtc] [ppp] [rcb] [tqp <queue_num>]]\n",
 		HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1);
 	dev_info(&h->pdev->dev, "%s", printf_buf);
 
 	memset(printf_buf, 0, HNS3_DBG_BUF_LEN);
-	strncat(printf_buf, "dump reg dcb [port_id] [pri_id] [pg_id]",
+	strncat(printf_buf, "dump reg dcb <port_id> <pri_id> <pg_id>",
 		HNS3_DBG_BUF_LEN - 1);
-	strncat(printf_buf + strlen(printf_buf), " [rq_id] [nq_id] [qset_id]\n",
+	strncat(printf_buf + strlen(printf_buf), " <rq_id> <nq_id> <qset_id>\n",
 		HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1);
 	dev_info(&h->pdev->dev, "%s", printf_buf);
 }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 0639250..1debe37 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -83,7 +83,7 @@ static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset)
 	ret = hclge_query_bd_num_cmd_send(hdev, desc);
 	if (ret) {
 		dev_err(&hdev->pdev->dev,
-			"get dfx bdnum fail, status is %d.\n", ret);
+			"get dfx bdnum fail, ret = %d\n", ret);
 		return ret;
 	}
 
@@ -110,12 +110,9 @@ static int hclge_dbg_cmd_send(struct hclge_dev *hdev,
 	}
 
 	ret = hclge_cmd_send(&hdev->hw, desc_src, bd_num);
-	if (ret) {
+	if (ret)
 		dev_err(&hdev->pdev->dev,
-			"read reg cmd send fail, status is %d.\n", ret);
-		return ret;
-	}
-
+			"cmd(0x%x) send fail, ret = %d\n", cmd, ret);
 	return ret;
 }
 
@@ -142,8 +139,11 @@ static void hclge_dbg_dump_reg_common(struct hclge_dev *hdev,
 	}
 
 	bd_num = hclge_dbg_get_dfx_bd_num(hdev, reg_msg->offset);
-	if (bd_num <= 0)
+	if (bd_num <= 0) {
+		dev_err(&hdev->pdev->dev, "get cmd(%d) bd num(%d) failed\n",
+			reg_msg->offset, bd_num);
 		return;
+	}
 
 	buf_len	 = sizeof(struct hclge_desc) * bd_num;
 	desc_src = kzalloc(buf_len, GFP_KERNEL);
@@ -331,7 +331,7 @@ static void hclge_dbg_dump_tc(struct hclge_dev *hdev)
 
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret) {
-		dev_err(&hdev->pdev->dev, "dump tc fail, status is %d.\n", ret);
+		dev_err(&hdev->pdev->dev, "dump tc fail, ret = %d\n", ret);
 		return;
 	}
 
@@ -433,7 +433,7 @@ static void hclge_dbg_dump_tm_pg(struct hclge_dev *hdev)
 	return;
 
 err_tm_pg_cmd_send:
-	dev_err(&hdev->pdev->dev, "dump tm_pg fail(0x%x), status is %d\n",
+	dev_err(&hdev->pdev->dev, "dump tm_pg fail(0x%x), ret = %d\n",
 		cmd, ret);
 }
 
@@ -545,7 +545,7 @@ static void hclge_dbg_dump_tm(struct hclge_dev *hdev)
 	return;
 
 err_tm_cmd_send:
-	dev_err(&hdev->pdev->dev, "dump tm fail(0x%x), status is %d\n",
+	dev_err(&hdev->pdev->dev, "dump tm fail(0x%x), ret = %d\n",
 		cmd, ret);
 }
 
@@ -634,7 +634,7 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev,
 	return;
 
 err_tm_map_cmd_send:
-	dev_err(&hdev->pdev->dev, "dump tqp map fail(0x%x), status is %d\n",
+	dev_err(&hdev->pdev->dev, "dump tqp map fail(0x%x), ret = %d\n",
 		cmd, ret);
 }
 
@@ -648,7 +648,7 @@ static void hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev)
 
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret) {
-		dev_err(&hdev->pdev->dev, "dump checksum fail, status is %d.\n",
+		dev_err(&hdev->pdev->dev, "dump checksum fail, ret = %d\n",
 			ret);
 		return;
 	}
@@ -672,7 +672,7 @@ static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev)
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret) {
 		dev_err(&hdev->pdev->dev,
-			"dump qos pri map fail, status is %d.\n", ret);
+			"dump qos pri map fail, ret = %d\n", ret);
 		return;
 	}
 
@@ -805,7 +805,7 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev)
 
 err_qos_cmd_send:
 	dev_err(&hdev->pdev->dev,
-		"dump qos buf cfg fail(0x%x), status is %d\n", cmd, ret);
+		"dump qos buf cfg fail(0x%x), ret = %d\n", cmd, ret);
 }
 
 static void hclge_dbg_dump_mng_table(struct hclge_dev *hdev)
@@ -963,7 +963,7 @@ void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev)
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret) {
 		dev_err(&hdev->pdev->dev,
-			"get firmware statistics bd number failed, ret=%d\n",
+			"get firmware statistics bd number failed, ret = %d\n",
 			ret);
 		return;
 	}
@@ -984,7 +984,7 @@ void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev)
 	if (ret) {
 		kfree(desc_src);
 		dev_err(&hdev->pdev->dev,
-			"get firmware statistics failed, ret=%d\n", ret);
+			"get firmware statistics failed, ret = %d\n", ret);
 		return;
 	}
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index fa85d9e..8a5b81d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7237,7 +7237,7 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p,
 	    is_broadcast_ether_addr(new_addr) ||
 	    is_multicast_ether_addr(new_addr)) {
 		dev_err(&hdev->pdev->dev,
-			"Change uc mac err! invalid mac:%p.\n",
+			"Change uc mac err! invalid mac:%pM.\n",
 			 new_addr);
 		return -EINVAL;
 	}
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 03/12] net: hns3: modify base parameter of kstrtouint in hclge_dbg_dump_tm_map
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

This patch replaces kstrtouint()'s patameter base with 0 in the
hclge_dbg_dump_tm_mac(), which makes it more flexible. Also
uses a macro to replace string "dump tm map", since it has been
used multiple times.

Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 3b4cd23..0639250 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -564,7 +564,7 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev,
 	int pri_id, ret;
 	u32 i;
 
-	ret = kstrtouint(&cmd_buf[12], 10, &queue_id);
+	ret = kstrtouint(cmd_buf, 0, &queue_id);
 	queue_id = (ret != 0) ? 0 : queue_id;
 
 	cmd = HCLGE_OPC_TM_NQ_TO_QS_LINK;
@@ -1099,6 +1099,7 @@ static void hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev)
 int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
 {
 #define DUMP_REG	"dump reg"
+#define DUMP_TM_MAP	"dump tm map"
 
 	struct hclge_vport *vport = hclge_get_vport(handle);
 	struct hclge_dev *hdev = vport->back;
@@ -1107,8 +1108,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
 		hclge_dbg_fd_tcam(hdev);
 	} else if (strncmp(cmd_buf, "dump tc", 7) == 0) {
 		hclge_dbg_dump_tc(hdev);
-	} else if (strncmp(cmd_buf, "dump tm map", 11) == 0) {
-		hclge_dbg_dump_tm_map(hdev, cmd_buf);
+	} else if (strncmp(cmd_buf, DUMP_TM_MAP, strlen(DUMP_TM_MAP)) == 0) {
+		hclge_dbg_dump_tm_map(hdev, &cmd_buf[sizeof(DUMP_TM_MAP)]);
 	} else if (strncmp(cmd_buf, "dump tm", 7) == 0) {
 		hclge_dbg_dump_tm(hdev);
 	} else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) {
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 11/12] net: hns3: check reset interrupt status when reset fails
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

Currently, the reset interrupt will be cleared firstly, so when
reset fails, if interrupt status register has reset interrupt,
it means there is a new coming reset.

Fixes: 72e2fb07997c ("net: hns3: clear reset interrupt status in hclge_irq_handle()")
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Reviewed-by: Peng Li <lipeng321@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 +++----
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 +
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 428f7c0..dc22b84 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3536,11 +3536,10 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev)
 		dev_info(&hdev->pdev->dev, "Reset pending %lu\n",
 			 hdev->reset_pending);
 		return true;
-	} else if ((hdev->reset_type != HNAE3_IMP_RESET) &&
-		   (hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG) &
-		    BIT(HCLGE_IMP_RESET_BIT))) {
+	} else if (hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS) &
+		   HCLGE_RESET_INT_M) {
 		dev_info(&hdev->pdev->dev,
-			 "reset failed because IMP Reset is pending\n");
+			 "reset failed because new reset interrupt\n");
 		hclge_clear_reset_cause(hdev);
 		return false;
 	} else if (hdev->reset_fail_cnt < MAX_RESET_FAIL_CNT) {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index a3bc382..437a9ff 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -164,6 +164,7 @@ enum HLCGE_PORT_TYPE {
 #define HCLGE_GLOBAL_RESET_BIT		0
 #define HCLGE_CORE_RESET_BIT		1
 #define HCLGE_IMP_RESET_BIT		2
+#define HCLGE_RESET_INT_M		GENMASK(2, 0)
 #define HCLGE_FUN_RST_ING		0x20C00
 #define HCLGE_FUN_RST_ING_B		0
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 10/12] net: hns3: add phy selftest function
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Yufeng Mo, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Yufeng Mo <moyufeng@huawei.com>

Currently, the loopback test supports only mac selftest and serdes
selftest. This patch adds phy selftest.

Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c |   7 +-
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 150 ++++++++++++++++++---
 2 files changed, 138 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 0332d6f..e219bb1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -59,7 +59,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         3
+#define HNS3_SELF_TEST_TYPE_NUM         4
 #define HNS3_NIC_LB_TEST_PKT_NUM	1
 #define HNS3_NIC_LB_TEST_RING_ID	0
 #define HNS3_NIC_LB_TEST_PACKET_SIZE	128
@@ -89,6 +89,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
 	case HNAE3_LOOP_SERIAL_SERDES:
 	case HNAE3_LOOP_PARALLEL_SERDES:
 	case HNAE3_LOOP_APP:
+	case HNAE3_LOOP_PHY:
 		ret = h->ae_algo->ops->set_loopback(h, loop, en);
 		break;
 	default:
@@ -330,6 +331,10 @@ static void hns3_self_test(struct net_device *ndev,
 	st_param[HNAE3_LOOP_PARALLEL_SERDES][1] =
 			h->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
 
+	st_param[HNAE3_LOOP_PHY][0] = HNAE3_LOOP_PHY;
+	st_param[HNAE3_LOOP_PHY][1] =
+			h->flags & HNAE3_SUPPORT_PHY_LOOPBACK;
+
 	if (if_running)
 		ndev->netdev_ops->ndo_stop(ndev);
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 9ef1f468..428f7c0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -53,6 +53,8 @@
 #define HCLGE_DFX_TQP_BD_OFFSET         11
 #define HCLGE_DFX_SSU_2_BD_OFFSET       12
 
+#define HCLGE_LINK_STATUS_MS	10
+
 static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps);
 static int hclge_init_vlan_config(struct hclge_dev *hdev);
 static void hclge_sync_vlan_filter(struct hclge_dev *hdev);
@@ -742,6 +744,12 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
 		count += 2;
 		handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
 		handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
+
+		if (hdev->hw.mac.phydev) {
+			count += 1;
+			handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK;
+		}
+
 	} else if (stringset == ETH_SS_STATS) {
 		count = ARRAY_SIZE(g_mac_stats_string) +
 			hclge_tqps_get_sset_count(handle, stringset);
@@ -6204,6 +6212,65 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
 			"mac enable fail, ret =%d.\n", ret);
 }
 
+static void hclge_phy_link_status_wait(struct hclge_dev *hdev,
+				       int link_ret)
+{
+#define HCLGE_PHY_LINK_STATUS_NUM  200
+
+	struct phy_device *phydev = hdev->hw.mac.phydev;
+	int i = 0;
+	int ret;
+
+	do {
+		ret = phy_read_status(phydev);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"phy update link status fail, ret = %d\n", ret);
+			return;
+		}
+
+		if (phydev->link == link_ret)
+			break;
+
+		msleep(HCLGE_LINK_STATUS_MS);
+	} while (++i < HCLGE_PHY_LINK_STATUS_NUM);
+}
+
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
+{
+#define HCLGE_MAC_LINK_STATUS_NUM  100
+
+	int i = 0;
+	int ret;
+
+	do {
+		ret = hclge_get_mac_link_status(hdev);
+		if (ret < 0)
+			return ret;
+		else if (ret == link_ret)
+			return 0;
+
+		msleep(HCLGE_LINK_STATUS_MS);
+	} while (++i < HCLGE_MAC_LINK_STATUS_NUM);
+	return -EBUSY;
+}
+
+static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
+					  bool is_phy)
+{
+#define HCLGE_LINK_STATUS_DOWN 0
+#define HCLGE_LINK_STATUS_UP   1
+
+	int link_ret;
+
+	link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
+
+	if (is_phy)
+		hclge_phy_link_status_wait(hdev, link_ret);
+
+	return hclge_mac_link_status_wait(hdev, link_ret);
+}
+
 static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
 {
 	struct hclge_config_mac_mode_cmd *req;
@@ -6246,14 +6313,8 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
 #define HCLGE_SERDES_RETRY_MS	10
 #define HCLGE_SERDES_RETRY_NUM	100
 
-#define HCLGE_MAC_LINK_STATUS_MS   10
-#define HCLGE_MAC_LINK_STATUS_NUM  100
-#define HCLGE_MAC_LINK_STATUS_DOWN 0
-#define HCLGE_MAC_LINK_STATUS_UP   1
-
 	struct hclge_serdes_lb_cmd *req;
 	struct hclge_desc desc;
-	int mac_link_ret = 0;
 	int ret, i = 0;
 	u8 loop_mode_b;
 
@@ -6276,10 +6337,8 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
 	if (en) {
 		req->enable = loop_mode_b;
 		req->mask = loop_mode_b;
-		mac_link_ret = HCLGE_MAC_LINK_STATUS_UP;
 	} else {
 		req->mask = loop_mode_b;
-		mac_link_ret = HCLGE_MAC_LINK_STATUS_DOWN;
 	}
 
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -6312,18 +6371,70 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
 
 	hclge_cfg_mac_mode(hdev, en);
 
-	i = 0;
-	do {
-		/* serdes Internal loopback, independent of the network cable.*/
-		msleep(HCLGE_MAC_LINK_STATUS_MS);
-		ret = hclge_get_mac_link_status(hdev);
-		if (ret == mac_link_ret)
-			return 0;
-	} while (++i < HCLGE_MAC_LINK_STATUS_NUM);
+	ret = hclge_mac_phy_link_status_wait(hdev, en, FALSE);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"serdes loopback config mac mode timeout\n");
+
+	return ret;
+}
 
-	dev_err(&hdev->pdev->dev, "config mac mode timeout\n");
+static int hclge_enable_phy_loopback(struct hclge_dev *hdev,
+				     struct phy_device *phydev)
+{
+	int ret;
 
-	return -EBUSY;
+	if (!phydev->suspended) {
+		ret = phy_suspend(phydev);
+		if (ret)
+			return ret;
+	}
+
+	ret = phy_resume(phydev);
+	if (ret)
+		return ret;
+
+	return phy_loopback(phydev, true);
+}
+
+static int hclge_disable_phy_loopback(struct hclge_dev *hdev,
+				      struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy_loopback(phydev, false);
+	if (ret)
+		return ret;
+
+	return phy_suspend(phydev);
+}
+
+static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en)
+{
+	struct phy_device *phydev = hdev->hw.mac.phydev;
+	int ret;
+
+	if (!phydev)
+		return -ENOTSUPP;
+
+	if (en)
+		ret = hclge_enable_phy_loopback(hdev, phydev);
+	else
+		ret = hclge_disable_phy_loopback(hdev, phydev);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"set phy loopback fail, ret = %d\n", ret);
+		return ret;
+	}
+
+	hclge_cfg_mac_mode(hdev, en);
+
+	ret = hclge_mac_phy_link_status_wait(hdev, en, TRUE);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"phy loopback config mac mode timeout\n");
+
+	return ret;
 }
 
 static int hclge_tqp_enable(struct hclge_dev *hdev, unsigned int tqp_id,
@@ -6363,6 +6474,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
 	case HNAE3_LOOP_PARALLEL_SERDES:
 		ret = hclge_set_serdes_loopback(hdev, en, loop_mode);
 		break;
+	case HNAE3_LOOP_PHY:
+		ret = hclge_set_phy_loopback(hdev, en);
+		break;
 	default:
 		ret = -ENOTSUPP;
 		dev_err(&hdev->pdev->dev,
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 01/12] net: hns3: code optimization for debugfs related to "dump reg"
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Zhongzhu Liu, Guangbin Huang, Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

From: Zhongzhu Liu <liuzhongzhu@huawei.com>

For making the code more readable, this patch uses a array to
keep the information about the dumping register, and then uses
it to parse the parameter cmd_buf which passing into
hclge_dbg_dump_reg_cmd().

Also replaces parameter "base" of kstrtouint with 0 in the
hclge_dbg_dump_reg_common(), which makes it more flexible.

Signed-off-by: Zhongzhu Liu <liuzhongzhu@huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 226 +++++++++++----------
 .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h |  16 ++
 2 files changed, 132 insertions(+), 110 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 025184a..a56f388 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -4,14 +4,80 @@
 #include <linux/device.h>
 
 #include "hclge_debugfs.h"
-#include "hclge_cmd.h"
 #include "hclge_main.h"
 #include "hclge_tm.h"
 #include "hnae3.h"
 
+static struct hclge_dbg_reg_type_info hclge_dbg_reg_info[] = {
+	{ .reg_type = "bios common",
+	  .dfx_msg = &hclge_dbg_bios_common_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_bios_common_reg),
+		       .offset = HCLGE_DBG_DFX_BIOS_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_BIOS_COMMON_REG } },
+	{ .reg_type = "ssu",
+	  .dfx_msg = &hclge_dbg_ssu_reg_0[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_0),
+		       .offset = HCLGE_DBG_DFX_SSU_0_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_SSU_REG_0 } },
+	{ .reg_type = "ssu",
+	  .dfx_msg = &hclge_dbg_ssu_reg_1[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_1),
+		       .offset = HCLGE_DBG_DFX_SSU_1_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_SSU_REG_1 } },
+	{ .reg_type = "ssu",
+	  .dfx_msg = &hclge_dbg_ssu_reg_2[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_2),
+		       .offset = HCLGE_DBG_DFX_SSU_2_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_SSU_REG_2 } },
+	{ .reg_type = "igu egu",
+	  .dfx_msg = &hclge_dbg_igu_egu_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_igu_egu_reg),
+		       .offset = HCLGE_DBG_DFX_IGU_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_IGU_EGU_REG } },
+	{ .reg_type = "rpu",
+	  .dfx_msg = &hclge_dbg_rpu_reg_0[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rpu_reg_0),
+		       .offset = HCLGE_DBG_DFX_RPU_0_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_RPU_REG_0 } },
+	{ .reg_type = "rpu",
+	  .dfx_msg = &hclge_dbg_rpu_reg_1[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rpu_reg_1),
+		       .offset = HCLGE_DBG_DFX_RPU_1_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_RPU_REG_1 } },
+	{ .reg_type = "ncsi",
+	  .dfx_msg = &hclge_dbg_ncsi_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ncsi_reg),
+		       .offset = HCLGE_DBG_DFX_NCSI_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_NCSI_REG } },
+	{ .reg_type = "rtc",
+	  .dfx_msg = &hclge_dbg_rtc_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rtc_reg),
+		       .offset = HCLGE_DBG_DFX_RTC_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_RTC_REG } },
+	{ .reg_type = "ppp",
+	  .dfx_msg = &hclge_dbg_ppp_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ppp_reg),
+		       .offset = HCLGE_DBG_DFX_PPP_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_PPP_REG } },
+	{ .reg_type = "rcb",
+	  .dfx_msg = &hclge_dbg_rcb_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rcb_reg),
+		       .offset = HCLGE_DBG_DFX_RCB_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_RCB_REG } },
+	{ .reg_type = "tqp",
+	  .dfx_msg = &hclge_dbg_tqp_reg[0],
+	  .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_tqp_reg),
+		       .offset = HCLGE_DBG_DFX_TQP_OFFSET,
+		       .cmd = HCLGE_OPC_DFX_TQP_REG } },
+};
+
 static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset)
 {
-	struct hclge_desc desc[4];
+#define HCLGE_GET_DFX_REG_TYPE_CNT	4
+
+	struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT];
+	int entries_per_desc;
+	int index;
 	int ret;
 
 	ret = hclge_query_bd_num_cmd_send(hdev, desc);
@@ -21,7 +87,9 @@ static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset)
 		return ret;
 	}
 
-	return (int)desc[offset / 6].data[offset % 6];
+	entries_per_desc = ARRAY_SIZE(desc[0].data);
+	index = offset % entries_per_desc;
+	return (int)desc[offset / entries_per_desc].data[index];
 }
 
 static int hclge_dbg_cmd_send(struct hclge_dev *hdev,
@@ -52,23 +120,28 @@ static int hclge_dbg_cmd_send(struct hclge_dev *hdev,
 }
 
 static void hclge_dbg_dump_reg_common(struct hclge_dev *hdev,
-				      struct hclge_dbg_dfx_message *dfx_message,
-				      const char *cmd_buf, int msg_num,
-				      int offset, enum hclge_opcode_type cmd)
+				      struct hclge_dbg_reg_type_info *reg_info,
+				      const char *cmd_buf)
 {
-#define BD_DATA_NUM       6
+#define IDX_OFFSET	1
 
+	const char *s = &cmd_buf[strlen(reg_info->reg_type) + IDX_OFFSET];
+	struct hclge_dbg_dfx_message *dfx_message = reg_info->dfx_msg;
+	struct hclge_dbg_reg_common_msg *reg_msg = &reg_info->reg_msg;
 	struct hclge_desc *desc_src;
 	struct hclge_desc *desc;
+	int entries_per_desc;
 	int bd_num, buf_len;
+	int index = 0;
+	int min_num;
 	int ret, i;
-	int index;
-	int max;
 
-	ret = kstrtouint(cmd_buf, 10, &index);
-	index = (ret != 0) ? 0 : index;
+	if (*s) {
+		ret = kstrtouint(s, 0, &index);
+		index = (ret != 0) ? 0 : index;
+	}
 
-	bd_num = hclge_dbg_get_dfx_bd_num(hdev, offset);
+	bd_num = hclge_dbg_get_dfx_bd_num(hdev, reg_msg->offset);
 	if (bd_num <= 0)
 		return;
 
@@ -80,22 +153,23 @@ static void hclge_dbg_dump_reg_common(struct hclge_dev *hdev,
 	}
 
 	desc = desc_src;
-	ret  = hclge_dbg_cmd_send(hdev, desc, index, bd_num, cmd);
-	if (ret != HCLGE_CMD_EXEC_SUCCESS) {
+	ret  = hclge_dbg_cmd_send(hdev, desc, index, bd_num, reg_msg->cmd);
+	if (ret) {
 		kfree(desc_src);
 		return;
 	}
 
-	max = (bd_num * BD_DATA_NUM) <= msg_num ?
-		(bd_num * BD_DATA_NUM) : msg_num;
+	entries_per_desc = ARRAY_SIZE(desc->data);
+	min_num = min_t(int, bd_num * entries_per_desc, reg_msg->msg_num);
 
 	desc = desc_src;
-	for (i = 0; i < max; i++) {
-		((i > 0) && ((i % BD_DATA_NUM) == 0)) ? desc++ : desc;
+	for (i = 0; i < min_num; i++) {
+		if (i > 0 && (i % entries_per_desc) == 0)
+			desc++;
 		if (dfx_message->flag)
 			dev_info(&hdev->pdev->dev, "%s: 0x%x\n",
 				 dfx_message->message,
-				 desc->data[i % BD_DATA_NUM]);
+				 desc->data[i % entries_per_desc]);
 
 		dfx_message++;
 	}
@@ -205,95 +279,25 @@ static void hclge_dbg_dump_dcb(struct hclge_dev *hdev, const char *cmd_buf)
 
 static void hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, const char *cmd_buf)
 {
-	int msg_num;
-
-	if (strncmp(&cmd_buf[9], "bios common", 11) == 0) {
-		msg_num = sizeof(hclge_dbg_bios_common_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_bios_common_reg,
-					  &cmd_buf[21], msg_num,
-					  HCLGE_DBG_DFX_BIOS_OFFSET,
-					  HCLGE_OPC_DFX_BIOS_COMMON_REG);
-	} else if (strncmp(&cmd_buf[9], "ssu", 3) == 0) {
-		msg_num = sizeof(hclge_dbg_ssu_reg_0) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_ssu_reg_0,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_SSU_0_OFFSET,
-					  HCLGE_OPC_DFX_SSU_REG_0);
-
-		msg_num = sizeof(hclge_dbg_ssu_reg_1) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_ssu_reg_1,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_SSU_1_OFFSET,
-					  HCLGE_OPC_DFX_SSU_REG_1);
-
-		msg_num = sizeof(hclge_dbg_ssu_reg_2) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_ssu_reg_2,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_SSU_2_OFFSET,
-					  HCLGE_OPC_DFX_SSU_REG_2);
-	} else if (strncmp(&cmd_buf[9], "igu egu", 7) == 0) {
-		msg_num = sizeof(hclge_dbg_igu_egu_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_igu_egu_reg,
-					  &cmd_buf[17], msg_num,
-					  HCLGE_DBG_DFX_IGU_OFFSET,
-					  HCLGE_OPC_DFX_IGU_EGU_REG);
-	} else if (strncmp(&cmd_buf[9], "rpu", 3) == 0) {
-		msg_num = sizeof(hclge_dbg_rpu_reg_0) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_rpu_reg_0,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_RPU_0_OFFSET,
-					  HCLGE_OPC_DFX_RPU_REG_0);
-
-		msg_num = sizeof(hclge_dbg_rpu_reg_1) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_rpu_reg_1,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_RPU_1_OFFSET,
-					  HCLGE_OPC_DFX_RPU_REG_1);
-	} else if (strncmp(&cmd_buf[9], "ncsi", 4) == 0) {
-		msg_num = sizeof(hclge_dbg_ncsi_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_ncsi_reg,
-					  &cmd_buf[14], msg_num,
-					  HCLGE_DBG_DFX_NCSI_OFFSET,
-					  HCLGE_OPC_DFX_NCSI_REG);
-	} else if (strncmp(&cmd_buf[9], "rtc", 3) == 0) {
-		msg_num = sizeof(hclge_dbg_rtc_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_rtc_reg,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_RTC_OFFSET,
-					  HCLGE_OPC_DFX_RTC_REG);
-	} else if (strncmp(&cmd_buf[9], "ppp", 3) == 0) {
-		msg_num = sizeof(hclge_dbg_ppp_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_ppp_reg,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_PPP_OFFSET,
-					  HCLGE_OPC_DFX_PPP_REG);
-	} else if (strncmp(&cmd_buf[9], "rcb", 3) == 0) {
-		msg_num = sizeof(hclge_dbg_rcb_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_rcb_reg,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_RCB_OFFSET,
-					  HCLGE_OPC_DFX_RCB_REG);
-	} else if (strncmp(&cmd_buf[9], "tqp", 3) == 0) {
-		msg_num = sizeof(hclge_dbg_tqp_reg) /
-			  sizeof(struct hclge_dbg_dfx_message);
-		hclge_dbg_dump_reg_common(hdev, hclge_dbg_tqp_reg,
-					  &cmd_buf[13], msg_num,
-					  HCLGE_DBG_DFX_TQP_OFFSET,
-					  HCLGE_OPC_DFX_TQP_REG);
-	} else if (strncmp(&cmd_buf[9], "dcb", 3) == 0) {
-		hclge_dbg_dump_dcb(hdev, &cmd_buf[13]);
-	} else {
+	struct hclge_dbg_reg_type_info *reg_info = &hclge_dbg_reg_info[0];
+	bool has_dump = false;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hclge_dbg_reg_info); i++) {
+		reg_info = &hclge_dbg_reg_info[i];
+		if (!strncmp(cmd_buf, reg_info->reg_type,
+			     strlen(reg_info->reg_type))) {
+			hclge_dbg_dump_reg_common(hdev, reg_info, cmd_buf);
+			has_dump = true;
+		}
+	}
+
+	if (strncmp(cmd_buf, "dcb", 3) == 0) {
+		hclge_dbg_dump_dcb(hdev, &cmd_buf[sizeof("dcb")]);
+		has_dump = true;
+	}
+
+	if (!has_dump) {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return;
 	}
@@ -1092,6 +1096,8 @@ static void hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev)
 
 int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
 {
+#define DUMP_REG	"dump reg"
+
 	struct hclge_vport *vport = hclge_get_vport(handle);
 	struct hclge_dev *hdev = vport->back;
 
@@ -1111,8 +1117,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
 		hclge_dbg_dump_qos_buf_cfg(hdev);
 	} else if (strncmp(cmd_buf, "dump mng tbl", 12) == 0) {
 		hclge_dbg_dump_mng_table(hdev);
-	} else if (strncmp(cmd_buf, "dump reg", 8) == 0) {
-		hclge_dbg_dump_reg_cmd(hdev, cmd_buf);
+	} else if (strncmp(cmd_buf, DUMP_REG, strlen(DUMP_REG)) == 0) {
+		hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]);
 	} else if (strncmp(cmd_buf, "dump reset info", 15) == 0) {
 		hclge_dbg_dump_rst_info(hdev);
 	} else if (strncmp(cmd_buf, "dump m7 info", 12) == 0) {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
index d055fda..80e5cc2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
@@ -4,6 +4,9 @@
 #ifndef __HCLGE_DEBUGFS_H
 #define __HCLGE_DEBUGFS_H
 
+#include <linux/etherdevice.h>
+#include "hclge_cmd.h"
+
 #define HCLGE_DBG_BUF_LEN	   256
 #define HCLGE_DBG_MNG_TBL_MAX	   64
 
@@ -63,11 +66,24 @@ struct hclge_dbg_bitmap_cmd {
 	};
 };
 
+struct hclge_dbg_reg_common_msg {
+	int msg_num;
+	int offset;
+	enum hclge_opcode_type cmd;
+};
+
 struct hclge_dbg_dfx_message {
 	int flag;
 	char message[60];
 };
 
+#define HCLGE_DBG_MAC_REG_TYPE_LEN	32
+struct hclge_dbg_reg_type_info {
+	const char *reg_type;
+	struct hclge_dbg_dfx_message *dfx_msg;
+	struct hclge_dbg_reg_common_msg reg_msg;
+};
+
 #pragma pack()
 
 static struct hclge_dbg_dfx_message hclge_dbg_bios_common_reg[] = {
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 02/12] net: hns3: use macro instead of magic number
From: Huazhong Tan @ 2019-08-28 14:23 UTC (permalink / raw)
  To: davem
  Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
	Huazhong Tan
In-Reply-To: <1567002196-63242-1-git-send-email-tanhuazhong@huawei.com>

This patch uses macro to replace some magic number.

Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 6 ++++--
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h | 3 ++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index a56f388..3b4cd23 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -774,7 +774,8 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev)
 	rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[1].data;
 	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
 		dev_info(&hdev->pdev->dev,
-			 "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i + 4,
+			 "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n",
+			 i + HCLGE_TC_NUM_ONE_DESC,
 			 rx_priv_wl->tc_wl[i].high, rx_priv_wl->tc_wl[i].low);
 
 	cmd = HCLGE_OPC_RX_COM_THRD_ALLOC;
@@ -796,7 +797,8 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev)
 	rx_com_thrd = (struct hclge_rx_com_thrd *)desc[1].data;
 	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
 		dev_info(&hdev->pdev->dev,
-			 "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i + 4,
+			 "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n",
+			 i + HCLGE_TC_NUM_ONE_DESC,
 			 rx_com_thrd->com_thrd[i].high,
 			 rx_com_thrd->com_thrd[i].low);
 	return;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
index 80e5cc2..38b7932 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
@@ -72,9 +72,10 @@ struct hclge_dbg_reg_common_msg {
 	enum hclge_opcode_type cmd;
 };
 
+#define	HCLGE_DBG_MAX_DFX_MSG_LEN	60
 struct hclge_dbg_dfx_message {
 	int flag;
-	char message[60];
+	char message[HCLGE_DBG_MAX_DFX_MSG_LEN];
 };
 
 #define HCLGE_DBG_MAC_REG_TYPE_LEN	32
-- 
2.7.4


^ permalink raw reply related

* [PATCH net 0/3] Fix issues in tc-taprio and tc-cbs
From: Vladimir Oltean @ 2019-08-28 14:48 UTC (permalink / raw)
  To: jhs, xiyou.wangcong, jiri, davem, vinicius.gomes, vedang.patel,
	leandro.maciel.dorileo
  Cc: netdev, Vladimir Oltean

This series fixes one panic and one WARN_ON found in the tc-taprio
qdisc, while trying to apply it:

- On an interface which is not multi-queue
- On an interface which has no carrier

The tc-cbs was also visually found to suffer of the same issue as
tc-taprio, and the fix was only compile-tested in that case.

Vladimir Oltean (3):
  taprio: Fix kernel panic in taprio_destroy
  taprio: Set default link speed to 10 Mbps in taprio_set_picos_per_byte
  net/sched: cbs: Set default link speed to 10 Mbps in cbs_set_port_rate

 net/sched/sch_cbs.c    | 19 +++++++++++--------
 net/sched/sch_taprio.c | 32 ++++++++++++++++++++------------
 2 files changed, 31 insertions(+), 20 deletions(-)

-- 
2.17.1


^ permalink raw reply

* [PATCH net 1/3] taprio: Fix kernel panic in taprio_destroy
From: Vladimir Oltean @ 2019-08-28 14:48 UTC (permalink / raw)
  To: jhs, xiyou.wangcong, jiri, davem, vinicius.gomes, vedang.patel,
	leandro.maciel.dorileo
  Cc: netdev, Vladimir Oltean
In-Reply-To: <20190828144829.32570-1-olteanv@gmail.com>

taprio_init may fail earlier than this line:

	list_add(&q->taprio_list, &taprio_list);

i.e. due to the net device not being multi queue.

Attempting to remove q from the global taprio_list when it is not part
of it will result in a kernel panic.

Fix it by iterating through the list and removing it only if found.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
 net/sched/sch_taprio.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 540bde009ea5..f1eea8c68011 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -1199,12 +1199,17 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
 
 static void taprio_destroy(struct Qdisc *sch)
 {
-	struct taprio_sched *q = qdisc_priv(sch);
+	struct taprio_sched *p, *q = qdisc_priv(sch);
 	struct net_device *dev = qdisc_dev(sch);
+	struct list_head *pos, *tmp;
 	unsigned int i;
 
 	spin_lock(&taprio_list_lock);
-	list_del(&q->taprio_list);
+	list_for_each_safe(pos, tmp, &taprio_list) {
+		p = list_entry(pos, struct taprio_sched, taprio_list);
+		if (p == q)
+			list_del(&q->taprio_list);
+	}
 	spin_unlock(&taprio_list_lock);
 
 	hrtimer_cancel(&q->advance_timer);
-- 
2.17.1


^ permalink raw reply related

* [PATCH net 3/3] net/sched: cbs: Set default link speed to 10 Mbps in cbs_set_port_rate
From: Vladimir Oltean @ 2019-08-28 14:48 UTC (permalink / raw)
  To: jhs, xiyou.wangcong, jiri, davem, vinicius.gomes, vedang.patel,
	leandro.maciel.dorileo
  Cc: netdev, Vladimir Oltean
In-Reply-To: <20190828144829.32570-1-olteanv@gmail.com>

The discussion to be made is absolutely the same as in the case of
previous patch ("taprio: Set default link speed to 10 Mbps in
taprio_set_picos_per_byte"). Nothing is lost when setting a default.

Cc: Leandro Dorileo <leandro.maciel.dorileo@intel.com>
Fixes: e0a7683d30e9 ("net/sched: cbs: fix port_rate miscalculation")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
 net/sched/sch_cbs.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
index 732e109c3055..810645b5c086 100644
--- a/net/sched/sch_cbs.c
+++ b/net/sched/sch_cbs.c
@@ -181,11 +181,6 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
 	s64 credits;
 	int len;
 
-	if (atomic64_read(&q->port_rate) == -1) {
-		WARN_ONCE(1, "cbs: dequeue() called with unknown port rate.");
-		return NULL;
-	}
-
 	if (q->credits < 0) {
 		credits = timediff_to_credits(now - q->last, q->idleslope);
 
@@ -303,11 +298,19 @@ static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
 static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q)
 {
 	struct ethtool_link_ksettings ecmd;
+	int speed = SPEED_10;
 	int port_rate = -1;
+	int err;
+
+	err = __ethtool_get_link_ksettings(dev, &ecmd);
+	if (err < 0)
+		goto skip;
+
+	if (ecmd.base.speed != SPEED_UNKNOWN)
+		speed = ecmd.base.speed;
 
-	if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
-	    ecmd.base.speed != SPEED_UNKNOWN)
-		port_rate = ecmd.base.speed * 1000 * BYTES_PER_KBIT;
+skip:
+	port_rate = speed * 1000 * BYTES_PER_KBIT;
 
 	atomic64_set(&q->port_rate, port_rate);
 	netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n",
-- 
2.17.1


^ permalink raw reply related

* [PATCH net 2/3] taprio: Set default link speed to 10 Mbps in taprio_set_picos_per_byte
From: Vladimir Oltean @ 2019-08-28 14:48 UTC (permalink / raw)
  To: jhs, xiyou.wangcong, jiri, davem, vinicius.gomes, vedang.patel,
	leandro.maciel.dorileo
  Cc: netdev, Vladimir Oltean
In-Reply-To: <20190828144829.32570-1-olteanv@gmail.com>

The taprio budget needs to be adapted at runtime according to interface
link speed. But that handling is problematic.

For one thing, installing a qdisc on an interface that doesn't have
carrier is not illegal. But taprio prints the following stack trace:

[   31.851373] ------------[ cut here ]------------
[   31.856024] WARNING: CPU: 1 PID: 207 at net/sched/sch_taprio.c:481 taprio_dequeue+0x1a8/0x2d4
[   31.864566] taprio: dequeue() called with unknown picos per byte.
[   31.864570] Modules linked in:
[   31.873701] CPU: 1 PID: 207 Comm: tc Not tainted 5.3.0-rc5-01199-g8838fe023cd6 #1689
[   31.881398] Hardware name: Freescale LS1021A
[   31.885661] [<c03133a4>] (unwind_backtrace) from [<c030d8cc>] (show_stack+0x10/0x14)
[   31.893368] [<c030d8cc>] (show_stack) from [<c10ac958>] (dump_stack+0xb4/0xc8)
[   31.900555] [<c10ac958>] (dump_stack) from [<c0349d04>] (__warn+0xe0/0xf8)
[   31.907395] [<c0349d04>] (__warn) from [<c0349d64>] (warn_slowpath_fmt+0x48/0x6c)
[   31.914841] [<c0349d64>] (warn_slowpath_fmt) from [<c0f38db4>] (taprio_dequeue+0x1a8/0x2d4)
[   31.923150] [<c0f38db4>] (taprio_dequeue) from [<c0f227b0>] (__qdisc_run+0x90/0x61c)
[   31.930856] [<c0f227b0>] (__qdisc_run) from [<c0ec82ac>] (net_tx_action+0x12c/0x2bc)
[   31.938560] [<c0ec82ac>] (net_tx_action) from [<c0302298>] (__do_softirq+0x130/0x3c8)
[   31.946350] [<c0302298>] (__do_softirq) from [<c03502a0>] (irq_exit+0xbc/0xd8)
[   31.953536] [<c03502a0>] (irq_exit) from [<c03a4808>] (__handle_domain_irq+0x60/0xb4)
[   31.961328] [<c03a4808>] (__handle_domain_irq) from [<c0754478>] (gic_handle_irq+0x58/0x9c)
[   31.969638] [<c0754478>] (gic_handle_irq) from [<c0301a8c>] (__irq_svc+0x6c/0x90)
[   31.977076] Exception stack(0xe8167b20 to 0xe8167b68)
[   31.982100] 7b20: e9d4bd80 00000cc0 000000cf 00000000 e9d4bd80 c1f38958 00000cc0 c1f38960
[   31.990234] 7b40: 00000001 000000cf 00000004 e9dc0800 00000000 e8167b70 c0f478ec c0f46d94
[   31.998363] 7b60: 60070013 ffffffff
[   32.001833] [<c0301a8c>] (__irq_svc) from [<c0f46d94>] (netlink_trim+0x18/0xd8)
[   32.009104] [<c0f46d94>] (netlink_trim) from [<c0f478ec>] (netlink_broadcast_filtered+0x34/0x414)
[   32.017930] [<c0f478ec>] (netlink_broadcast_filtered) from [<c0f47cec>] (netlink_broadcast+0x20/0x28)
[   32.027102] [<c0f47cec>] (netlink_broadcast) from [<c0eea378>] (rtnetlink_send+0x34/0x88)
[   32.035238] [<c0eea378>] (rtnetlink_send) from [<c0f25890>] (notify_and_destroy+0x2c/0x44)
[   32.043461] [<c0f25890>] (notify_and_destroy) from [<c0f25e08>] (qdisc_graft+0x398/0x470)
[   32.051595] [<c0f25e08>] (qdisc_graft) from [<c0f27a00>] (tc_modify_qdisc+0x3a4/0x724)
[   32.059470] [<c0f27a00>] (tc_modify_qdisc) from [<c0ee4c84>] (rtnetlink_rcv_msg+0x260/0x2ec)
[   32.067864] [<c0ee4c84>] (rtnetlink_rcv_msg) from [<c0f4a988>] (netlink_rcv_skb+0xb8/0x110)
[   32.076172] [<c0f4a988>] (netlink_rcv_skb) from [<c0f4a170>] (netlink_unicast+0x1b4/0x22c)
[   32.084392] [<c0f4a170>] (netlink_unicast) from [<c0f4a5e4>] (netlink_sendmsg+0x33c/0x380)
[   32.092614] [<c0f4a5e4>] (netlink_sendmsg) from [<c0ea9f40>] (sock_sendmsg+0x14/0x24)
[   32.100403] [<c0ea9f40>] (sock_sendmsg) from [<c0eaa780>] (___sys_sendmsg+0x214/0x228)
[   32.108279] [<c0eaa780>] (___sys_sendmsg) from [<c0eabad0>] (__sys_sendmsg+0x50/0x8c)
[   32.116068] [<c0eabad0>] (__sys_sendmsg) from [<c0301000>] (ret_fast_syscall+0x0/0x54)
[   32.123938] Exception stack(0xe8167fa8 to 0xe8167ff0)
[   32.128960] 7fa0:                   b6fa68c8 000000f8 00000003 bea142d0 00000000 00000000
[   32.137093] 7fc0: b6fa68c8 000000f8 0052154c 00000128 5d6468a2 00000000 00000028 00558c9c
[   32.145224] 7fe0: 00000070 bea14278 00530d64 b6e17e64
[   32.150659] ---[ end trace 2139c9827c3e5177 ]---

This happens because the qdisc ->dequeue callback gets called. Which
again is not illegal, the qdisc will dequeue even when the interface is
up but doesn't have carrier (and hence SPEED_UNKNOWN), and the frames
will be dropped further down the stack in dev_direct_xmit().

And, at the end of the day, for what? For calculating the initial budget
of an interface which is non-operational at the moment and where frames
will get dropped anyway.

So if we can't figure out the link speed, default to SPEED_10 and move
along. We can also remove the runtime check now.

Cc: Leandro Dorileo <leandro.maciel.dorileo@intel.com>
Fixes: 7b9eba7ba0c1 ("net/sched: taprio: fix picos_per_byte miscalculation")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
 net/sched/sch_taprio.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index f1eea8c68011..645ae744390b 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -477,11 +477,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
 	u32 gate_mask;
 	int i;
 
-	if (atomic64_read(&q->picos_per_byte) == -1) {
-		WARN_ONCE(1, "taprio: dequeue() called with unknown picos per byte.");
-		return NULL;
-	}
-
 	rcu_read_lock();
 	entry = rcu_dereference(q->current_entry);
 	/* if there's no entry, it means that the schedule didn't
@@ -954,12 +949,20 @@ static void taprio_set_picos_per_byte(struct net_device *dev,
 				      struct taprio_sched *q)
 {
 	struct ethtool_link_ksettings ecmd;
-	int picos_per_byte = -1;
+	int speed = SPEED_10;
+	int picos_per_byte;
+	int err;
+
+	err = __ethtool_get_link_ksettings(dev, &ecmd);
+	if (err < 0)
+		goto skip;
+
+	if (ecmd.base.speed != SPEED_UNKNOWN)
+		speed = ecmd.base.speed;
 
-	if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
-	    ecmd.base.speed != SPEED_UNKNOWN)
-		picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
-					   ecmd.base.speed * 1000 * 1000);
+skip:
+	picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
+				   speed * 1000 * 1000);
 
 	atomic64_set(&q->picos_per_byte, picos_per_byte);
 	netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
-- 
2.17.1


^ permalink raw reply related

* [RFC PATCH 0/1] Fix PHYLINK handling of ethtool ksettings with no PHY
From: Vladimir Oltean @ 2019-08-28 14:58 UTC (permalink / raw)
  To: linux, andrew, f.fainelli, asolokha; +Cc: netdev, Vladimir Oltean

Logically speaking, this patch pertains to the "Fix issues in tc-taprio
and tc-cbs" series at:
https://patchwork.ozlabs.org/project/netdev/list/?series=127821&state=*

The reason why I did not submit this patch together with those is that I
don't know whether the error condition can happen in current mainline
Linux at the moment. I am running Arseny's RFC patch "gianfar: convert
to phylink" and have found that __ethtool_get_link_ksettings returns a
speed of 0 instead of SPEED_UNKNOWN when there is no PHY connected.

Gianfar has carried this oddity over from its PHYLIB days, where it
connects "late" to the PHY. I am not sure whether PHYLINK, gianfar, or
both, need to be changed. Comments welcome.

Vladimir Oltean (1):
  phylink: Set speed to SPEED_UNKNOWN when there is no PHY connected

 drivers/net/phy/phylink.c | 1 +
 1 file changed, 1 insertion(+)

-- 
2.17.1


^ permalink raw reply

* [RFC PATCH 1/1] phylink: Set speed to SPEED_UNKNOWN when there is no PHY connected
From: Vladimir Oltean @ 2019-08-28 14:58 UTC (permalink / raw)
  To: linux, andrew, f.fainelli, asolokha; +Cc: netdev, Vladimir Oltean, Russell King
In-Reply-To: <20190828145802.3609-1-olteanv@gmail.com>

phylink_ethtool_ksettings_get can be called while the interface may not
even be up, which should not be a problem. But there are drivers (e.g.
gianfar) which connect to the PHY in .ndo_open and disconnect in
.ndo_close. While odd, to my knowledge this is again not illegal and
there may be more that do the same. But PHYLINK for example has this
check in phylink_ethtool_ksettings_get:

	if (pl->phydev) {
		phy_ethtool_ksettings_get(pl->phydev, kset);
	} else {
		kset->base.port = pl->link_port;
	}

So it will not populate kset->base.speed if there is no PHY connected.
The speed will be 0, by way of a previous memset. Not SPEED_UNKNOWN.
It is arguable whether that is legal or not. include/uapi/linux/ethtool.h
says:

	All values 0 to INT_MAX are legal.

By that measure it may be. But it sure would make users of the
__ethtool_get_link_ksettings API need make more complicated checks
(against -1, against 0, 1, etc). So far the kernel community has been ok
with just checking for SPEED_UNKNOWN.

Take net/sched/sch_taprio.c for example. The check in
taprio_set_picos_per_byte is currently not robust enough and will
trigger this division by zero, due to PHYLINK not setting SPEED_UNKNOWN:

	if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
	    ecmd.base.speed != SPEED_UNKNOWN)
		picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
					   ecmd.base.speed * 1000 * 1000);

[   27.109992] Division by zero in kernel.
[   27.113842] CPU: 1 PID: 198 Comm: tc Not tainted 5.3.0-rc5-01246-gc4006b8c2637-dirty #212
[   27.121974] Hardware name: Freescale LS1021A
[   27.126234] [<c03132e0>] (unwind_backtrace) from [<c030d8b8>] (show_stack+0x10/0x14)
[   27.133938] [<c030d8b8>] (show_stack) from [<c10b21b0>] (dump_stack+0xb0/0xc4)
[   27.141124] [<c10b21b0>] (dump_stack) from [<c10af97c>] (Ldiv0_64+0x8/0x18)
[   27.148052] [<c10af97c>] (Ldiv0_64) from [<c0700260>] (div64_u64+0xcc/0xf0)
[   27.154978] [<c0700260>] (div64_u64) from [<c07002d0>] (div64_s64+0x4c/0x68)
[   27.161993] [<c07002d0>] (div64_s64) from [<c0f3d890>] (taprio_set_picos_per_byte+0xe8/0xf4)
[   27.170388] [<c0f3d890>] (taprio_set_picos_per_byte) from [<c0f3f614>] (taprio_change+0x668/0xcec)
[   27.179302] [<c0f3f614>] (taprio_change) from [<c0f2bc24>] (qdisc_create+0x1fc/0x4f4)
[   27.187091] [<c0f2bc24>] (qdisc_create) from [<c0f2c0c8>] (tc_modify_qdisc+0x1ac/0x6f8)
[   27.195055] [<c0f2c0c8>] (tc_modify_qdisc) from [<c0ee9604>] (rtnetlink_rcv_msg+0x268/0x2dc)
[   27.203449] [<c0ee9604>] (rtnetlink_rcv_msg) from [<c0f4fef0>] (netlink_rcv_skb+0xe0/0x114)
[   27.211756] [<c0f4fef0>] (netlink_rcv_skb) from [<c0f4f6cc>] (netlink_unicast+0x1b4/0x22c)
[   27.219977] [<c0f4f6cc>] (netlink_unicast) from [<c0f4fa84>] (netlink_sendmsg+0x284/0x340)
[   27.228198] [<c0f4fa84>] (netlink_sendmsg) from [<c0eae5fc>] (sock_sendmsg+0x14/0x24)
[   27.235988] [<c0eae5fc>] (sock_sendmsg) from [<c0eaedf8>] (___sys_sendmsg+0x214/0x228)
[   27.243863] [<c0eaedf8>] (___sys_sendmsg) from [<c0eb015c>] (__sys_sendmsg+0x50/0x8c)
[   27.251652] [<c0eb015c>] (__sys_sendmsg) from [<c0301000>] (ret_fast_syscall+0x0/0x54)
[   27.259524] Exception stack(0xe8045fa8 to 0xe8045ff0)
[   27.264546] 5fa0:                   b6f608c8 000000f8 00000003 bed7e2f0 00000000 00000000
[   27.272681] 5fc0: b6f608c8 000000f8 004ce54c 00000128 5d3ce8c7 00000000 00000026 00505c9c
[   27.280812] 5fe0: 00000070 bed7e298 004ddd64 b6dd1e64

Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Fixes: 9525ae83959b ("phylink: add phylink infrastructure")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
 drivers/net/phy/phylink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a45c5de96ab1..3522eaf3e80c 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1112,6 +1112,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
 	if (pl->phydev) {
 		phy_ethtool_ksettings_get(pl->phydev, kset);
 	} else {
+		kset->base.speed = SPEED_UNKNOWN;
 		kset->base.port = pl->link_port;
 	}
 
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH rdma-next v3 0/3] ODP support for mlx5 DC QPs
From: Jason Gunthorpe @ 2019-08-28 15:18 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, RDMA mailing list, Michael Guralnik, Saeed Mahameed,
	linux-netdev
In-Reply-To: <20190828070620.GD4725@mtr-leonro.mtl.com>

On Wed, Aug 28, 2019 at 10:06:20AM +0300, Leon Romanovsky wrote:
> On Tue, Aug 27, 2019 at 12:51:40PM -0300, Jason Gunthorpe wrote:
> > On Mon, Aug 19, 2019 at 03:08:12PM +0300, Leon Romanovsky wrote:
> > > From: Leon Romanovsky <leonro@mellanox.com>
> > >
> > > Changelog
> > >  v3:
> > >  * Rewrote patches to expose through DEVX without need to change mlx5-abi.h at all.
> > >  v2: https://lore.kernel.org/linux-rdma/20190806074807.9111-1-leon@kernel.org
> > >  * Fixed reserved_* field wrong name (Saeed M.)
> > >  * Split first patch to two patches, one for mlx5-next and one for  rdma-next. (Saeed M.)
> > >  v1: https://lore.kernel.org/linux-rdma/20190804100048.32671-1-leon@kernel.org
> > >  * Fixed alignment to u64 in mlx5-abi.h (Gal P.)
> > >  v0: https://lore.kernel.org/linux-rdma/20190801122139.25224-1-leon@kernel.org
> > >
> > > >From Michael,
> > >
> > > The series adds support for on-demand paging for DC transport.
> > >
> > > As DC is mlx-only transport, the capabilities are exposed
> > > to the user using DEVX objects and later on through mlx5dv_query_device.
> > >
> > > Thanks
> > >
> > > Michael Guralnik (3):
> > >   net/mlx5: Set ODP capabilities for DC transport to max
> > >   IB/mlx5: Remove check of FW capabilities in ODP page fault handling
> > >   IB/mlx5: Add page fault handler for DC initiator WQE
> >
> > This seems fine, can you put the commit on the shared branch?
> 
> Thanks, applied to mlx5-next
> 00679b631edd net/mlx5: Set ODP capabilities for DC transport to max

Done, thanks

Jason

^ permalink raw reply

* Re: [RFC PATCH 1/2] gianfar: convert to phylink
From: Vladimir Oltean @ 2019-08-28 15:20 UTC (permalink / raw)
  To: Arseny Solokha
  Cc: Claudiu Manoil, Russell King, Ioana Ciornei, Andrew Lunn, netdev,
	Florian Fainelli
In-Reply-To: <CA+h21hruqt6nGG5ksDSwrGH_w5GtGF4fjAMCWJne7QJrjusERQ@mail.gmail.com>

Hi Arseny,

On Sat, 24 Aug 2019 at 18:21, Vladimir Oltean <olteanv@gmail.com> wrote:
>
> Hi Arseny.
>
> On Tue, 30 Jul 2019 at 17:40, Arseny Solokha <asolokha@kb.kras.ru> wrote:
> >
> > > Hi Arseny,
> > >
> > > Nice project!
> >
> > Vladimir, Russell, thanks for your review. I'm on vacation now, so won't fully
> > address your comments in a few weeks: while I can build the code, I won't have
> > access to hardware to test.
> >
> > So it seems this patch will turn into a series where we'll have some cleanup
> > patches preceding the actual conversion (and the latter will also contain a
> > documentation change in Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
> > which I've overlooked in the first submission). I'll try to post trivial
> > cleanups independently while still on vacation.
> >
>
> Yes, ideally the cleanup would be separate from the conversion.
>
> >
> > >> @@ -891,11 +912,21 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
> > >>
> > >>         err = of_property_read_string(np, "phy-connection-type", &ctype);
> > >>
> > >> -       /* We only care about rgmii-id.  The rest are autodetected */
> > >> -       if (err == 0 && !strcmp(ctype, "rgmii-id"))
> > >> -               priv->interface = PHY_INTERFACE_MODE_RGMII_ID;
> > >> -       else
> > >> +       /* We only care about rgmii-id and sgmii - the former
> > >> +        * is indistinguishable from rgmii in hardware, and phylink needs
> > >> +        * the latter to be set appropriately for correct phy configuration.
> > >> +        * The rest are autodetected
> > >> +        */
> > >> +       if (err == 0) {
> > >> +               if (!strcmp(ctype, "rgmii-id"))
> > >> +                       priv->interface = PHY_INTERFACE_MODE_RGMII_ID;
> > >> +               else if (!strcmp(ctype, "sgmii"))
> > >> +                       priv->interface = PHY_INTERFACE_MODE_SGMII;
> > >> +               else
> > >> +                       priv->interface = PHY_INTERFACE_MODE_MII;
> > >> +       } else {
> > >>                 priv->interface = PHY_INTERFACE_MODE_MII;
> > >> +       }
> > >>
> > >
> > > No. Don't do this. Just do:
> > >
> > >     err = of_get_phy_mode(np);
> > >     if (err < 0)
> > >         goto err_grp_init;
> > >
> > >     priv->interface = err;
> > >
> > >>         if (of_find_property(np, "fsl,magic-packet", NULL))
> > >>                 priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
> > >> @@ -903,19 +934,21 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
> > >>         if (of_get_property(np, "fsl,wake-on-filer", NULL))
> > >>                 priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER;
> > >>
> > >> -       priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
> > >> +       priv->device_node = np;
> > >> +       priv->speed = SPEED_UNKNOWN;
> > >>
> > >> -       /* In the case of a fixed PHY, the DT node associated
> > >> -        * to the PHY is the Ethernet MAC DT node.
> > >> -        */
> > >> -       if (!priv->phy_node && of_phy_is_fixed_link(np)) {
> > >> -               err = of_phy_register_fixed_link(np);
> > >> -               if (err)
> > >> -                       goto err_grp_init;
> > >> +       priv->phylink_config.dev = &priv->ndev->dev;
> > >> +       priv->phylink_config.type = PHYLINK_NETDEV;
> > >>
> > >> -               priv->phy_node = of_node_get(np);
> > >> +       phylink = phylink_create(&priv->phylink_config, of_fwnode_handle(np),
> > >> +                                priv->interface, &gfar_phylink_ops);
> > >
> > > You introduced a bug here.
> > > of_phy_connect used to take the PHY interface type (for good or bad)
> > > from gfar_get_interface() (which is reconstructing it from the MAC
> > > registers).
> > > You are now passing the PHY interface type to phylink_create from the
> > > "phy-connection-type" DT property.
> > > At the very least, you are breaking LS1021A which uses phy-mode
> > > instead of phy-connection-type (hence my comment above to use the
> > > generic OF helper).
> > > Actually I think you just uncovered a latent bug, in that the DT
> > > bindings for phy-mode didn't mean much at all to the driver - it would
> > > rely on what the bootloader had set up.
> > > Actually DT bindings for phy-connection-type were most likely simply
> > > bolt on on top of gianfar when they figured they couldn't just
> > > auto-detect the various species of required RGMII delays.
> > > But gfar_get_interface is a piece of history that was introduced in
> > > the same commit as the enum phy_interface_t itself: e8a2b6a42073
> > > ("[PATCH] PHY: Add support for configuring the PHY connection
> > > interface"). Its time has come.
> >
> > <…>
> >
> > >>         }
> > >>
> > >> +       priv->tbi_phy = NULL;
> > >> +       interface = gfar_get_interface(dev);
> > >
> > > Be consistent and just go for priv->interface. Nobody's changing it anyway.
> >
> > So if I get you right, I'm supposed to drop gfar_get_interface() and rely on DT
> > bindings entirely?
> >
>
> Oof, I checked arch/powerpc/boot/dts/fsl and the following boards
> using the gianfar driver are guilty of populating phy-handle but not
> phy-connection-type:
> mpc8540ads
> mpc8541cds
> mpc8548cds_32b
> mpc8548cds_36b
> mpc8555cds
> mpc8560ads
> mpc8568mds
> ppa8548
>
> I think a sane logic for populating priv->interface would be:
> - Attempt of_get_phy_mode
> - If phy-mode or phy-connection-type properties are not found, revert
> to gfar_get_interface for the legacy blobs above.
>
> >
> > >> @@ -3387,23 +3384,6 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id)
> > >>         return IRQ_HANDLED;
> > >>  }
> > >>
> > >> -/* Called every time the controller might need to be made
> > >> - * aware of new link state.  The PHY code conveys this
> > >> - * information through variables in the phydev structure, and this
> > >> - * function converts those variables into the appropriate
> > >> - * register values, and can bring down the device if needed.
> > >> - */
> > >> -static void adjust_link(struct net_device *dev)
> > >> -{
> > >> -       struct gfar_private *priv = netdev_priv(dev);
> > >> -       struct phy_device *phydev = dev->phydev;
> > >> -
> > >> -       if (unlikely(phydev->link != priv->oldlink ||
> > >> -                    (phydev->link && (phydev->duplex != priv->oldduplex ||
> > >> -                                      phydev->speed != priv->oldspeed))))
> > >> -               gfar_update_link_state(priv);
> > >> -}
> > >
> > > Getting rid of the cruft from this function deserves its own patch.
> >
> > How am I supposed to remove it without breaking the PHYLIB-based driver? Or do
> > you mean making it call gfar_update_link_state() just before the conversion
> > which will then remove adjust_link() altogether?
> >
>
> I don't know, if you can't refactor without breaking anything then ok.
>
> >
> > >>
> > >>         if (unlikely(test_bit(GFAR_RESETTING, &priv->state)))
> > >>                 return;
> > >>
> > >> -       if (phydev->link) {
> > >> -               u32 tempval1 = gfar_read(&regs->maccfg1);
> > >> -               u32 tempval = gfar_read(&regs->maccfg2);
> > >> -               u32 ecntrl = gfar_read(&regs->ecntrl);
> > >> -               u32 tx_flow_oldval = (tempval1 & MACCFG1_TX_FLOW);
> > >> +       if (unlikely(phylink_autoneg_inband(mode)))
> > >> +               return;
> > >>
> > >> -               if (phydev->duplex != priv->oldduplex) {
> > >> -                       if (!(phydev->duplex))
> > >> -                               tempval &= ~(MACCFG2_FULL_DUPLEX);
> > >> -                       else
> > >> -                               tempval |= MACCFG2_FULL_DUPLEX;
> > >> +       maccfg1 = gfar_read(&regs->maccfg1);
> > >> +       maccfg2 = gfar_read(&regs->maccfg2);
> > >> +       ecntrl = gfar_read(&regs->ecntrl);
> > >>
> > >> -                       priv->oldduplex = phydev->duplex;
> > >> -               }
> > >> +       new_maccfg2 = maccfg2 & ~(MACCFG2_FULL_DUPLEX | MACCFG2_IF);
> > >> +       new_ecntrl = ecntrl & ~ECNTRL_R100;
> > >>
> > >> -               if (phydev->speed != priv->oldspeed) {
> > >> -                       switch (phydev->speed) {
> > >> -                       case 1000:
> > >> -                               tempval =
> > >> -                                   ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
> > >> +       if (state->duplex)
> > >> +               new_maccfg2 |= MACCFG2_FULL_DUPLEX;
> > >>
> > >> -                               ecntrl &= ~(ECNTRL_R100);
> > >> -                               break;
> > >> -                       case 100:
> > >> -                       case 10:
> > >> -                               tempval =
> > >> -                                   ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
> > >> -
> > >> -                               /* Reduced mode distinguishes
> > >> -                                * between 10 and 100
> > >> -                                */
> > >> -                               if (phydev->speed == SPEED_100)
> > >> -                                       ecntrl |= ECNTRL_R100;
> > >> -                               else
> > >> -                                       ecntrl &= ~(ECNTRL_R100);
> > >> -                               break;
> > >> -                       default:
> > >> -                               netif_warn(priv, link, priv->ndev,
> > >> -                                          "Ack!  Speed (%d) is not 10/100/1000!\n",
> > >> -                                          phydev->speed);
> > >
> > > Please 1. remove "Ack!" 2. treat SPEED_UNKNOWN here by setting the MAC
> > > into a low-power state (e.g. 10 Mbps - the power savings are real).
> > > Don't print that Speed -1 is not 10/100/1000, we know that.
> >
> > In my first conversion attempt I see "Ack!" when changing link speed on when
> > shutting it down, so switching to 10 Mbps doesn't seem right for me—hence early
> > return in this case. Maybe I'm doing something wrong here.
> >
>
> When mac_config calls with SPEED_UNKNOWN, the link is down, and you
> can put the MAC in the lowest energy state it can go to (10 Mbps, in
> this case). Or so I've been told. Maybe Russell can chime in. Anyway,
> you don't need to print anything, there's lots of prints from PHYLINK
> already.
>
> >
> > >> diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
> > >> index 3433b46b90c1..146b30d07789 100644
> > >> --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
> > >> +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
> > >> @@ -35,7 +35,7 @@
> > >>  #include <asm/types.h>
> > >>  #include <linux/ethtool.h>
> > >>  #include <linux/mii.h>
> > >> -#include <linux/phy.h>
> > >> +#include <linux/phylink.h>
> > >>  #include <linux/sort.h>
> > >>  #include <linux/if_vlan.h>
> > >>  #include <linux/of_platform.h>
> > >> @@ -207,12 +207,10 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs,
> > >>  static unsigned int gfar_usecs2ticks(struct gfar_private *priv,
> > >>                                      unsigned int usecs)
> > >>  {
> > >> -       struct net_device *ndev = priv->ndev;
> > >> -       struct phy_device *phydev = ndev->phydev;
> > >
> > > Are you sure this still works? You missed a ndev->phydev check from
> > > gfar_gcoalesce, where this is called from. Technically you can still
> > > check ndev->phydev, it's just that PHYLINK doesn't guarantee you'll
> > > have one (e.g. fixed-link interfaces).
> >
> > It still works for RGMII PHYs, SGMII and 1000Base-X in my testing. I didn't
> > check it with fixed-link, though.
> >
> >
> > >> @@ -1519,6 +1472,24 @@ static int gfar_get_ts_info(struct net_device *dev,
> > >>         return 0;
> > >>  }
> > >>
> > >> +/* Set link ksettings (phy address, speed) for ethtools */
> > >
> > > ethtool, not ethtools. Also, I'm not quite sure what you mean by
> > > setting the "phy address" with ethtool.
> >
> > Well, I know where I've copied it from… Thanks for pointing it out.
>
> Regards,
> -Vladimir

Coming back to your patch.
Here is a gfar_reset_task gone horribly wrong, due to it not holding
rtnl_lock while calling phylink_stop:

[ 4115.081902] ------------[ cut here ]------------
[ 4115.086544] WARNING: CPU: 1 PID: 0 at net/sched/sch_generic.c:443
dev_watchdog+0x2ec/0x2f0
[ 4115.094802] NETDEV WATCHDOG: eth2 (fsl-gianfar): transmit queue 0 timed out
[ 4115.101727] Modules linked in:
[ 4115.104794] CPU: 1 PID: 0 Comm: swapper/1 Not tainted
5.3.0-rc6-01275-g246284a4920a-dirty #251
[ 4115.113360] Hardware name: Freescale LS1021A
[ 4115.117635] [<c03132e0>] (unwind_backtrace) from [<c030d8b8>]
(show_stack+0x10/0x14)
[ 4115.125351] [<c030d8b8>] (show_stack) from [<c10b41f0>]
(dump_stack+0xb0/0xc4)
[ 4115.132550] [<c10b41f0>] (dump_stack) from [<c0349dc8>] (__warn+0xf8/0x110)
[ 4115.139488] [<c0349dc8>] (__warn) from [<c0349e24>]
(warn_slowpath_fmt+0x44/0x68)
[ 4115.146942] [<c0349e24>] (warn_slowpath_fmt) from [<c0f28a4c>]
(dev_watchdog+0x2ec/0x2f0)
[ 4115.155089] [<c0f28a4c>] (dev_watchdog) from [<c03c2800>]
(call_timer_fn+0x3c/0x18c)
[ 4115.162806] [<c03c2800>] (call_timer_fn) from [<c03c2a2c>]
(expire_timers+0xdc/0x144)
[ 4115.170608] [<c03c2a2c>] (expire_timers) from [<c03c2d38>]
(run_timer_softirq+0xac/0x1d4)
[ 4115.178754] [<c03c2d38>] (run_timer_softirq) from [<c030221c>]
(__do_softirq+0xb4/0x364)
[ 4115.186815] [<c030221c>] (__do_softirq) from [<c03502c0>]
(irq_exit+0xbc/0xd8)
[ 4115.194012] [<c03502c0>] (irq_exit) from [<c03a426c>]
(__handle_domain_irq+0x60/0xb4)
[ 4115.201818] [<c03a426c>] (__handle_domain_irq) from [<c0754260>]
(gic_handle_irq+0x58/0x9c)
[ 4115.210139] [<c0754260>] (gic_handle_irq) from [<c0301a8c>]
(__irq_svc+0x6c/0x90)
[ 4115.217586] Exception stack(0xea8cff58 to 0xea8cffa0)
[ 4115.222613] ff40:
    00000000 0010afbc
[ 4115.230756] ff60: eb6c1330 c031ecc0 ea8ce000 c1d064ac c1d064f0
00000002 00000000 00000000
[ 4115.238900] ff80: c1c80ba8 ea8cffb0 00000000 ea8cffa8 c0309db4
c0309db8 600f0013 ffffffff
[ 4115.247049] [<c0301a8c>] (__irq_svc) from [<c0309db8>]
(arch_cpu_idle+0x38/0x3c)
[ 4115.254420] [<c0309db8>] (arch_cpu_idle) from [<c037aa04>]
(do_idle+0x1c8/0x2a4)
[ 4115.261789] [<c037aa04>] (do_idle) from [<c037ad7c>]
(cpu_startup_entry+0x18/0x1c)
[ 4115.269328] [<c037ad7c>] (cpu_startup_entry) from [<8030256c>] (0x8030256c)
[ 4115.276288] ---[ end trace c31a413a826ed6df ]---
[ 4115.291055] ------------[ cut here ]------------
[ 4115.295671] WARNING: CPU: 1 PID: 260 at
drivers/net/phy/phylink.c:1013 phylink_stop+0xd4/0xd8
[ 4115.304165] RTNL: assertion failed at drivers/net/phy/phylink.c (1013)
[ 4115.310651] Modules linked in:
[ 4115.313707] CPU: 1 PID: 260 Comm: kworker/1:4 Tainted: G        W
      5.3.0-rc6-01275-g246284a4920a-dirty #251
[ 4115.323996] Hardware name: Freescale LS1021A
[ 4115.328245] Workqueue: events gfar_reset_task
[ 4115.332589] [<c03132e0>] (unwind_backtrace) from [<c030d8b8>]
(show_stack+0x10/0x14)
[ 4115.340293] [<c030d8b8>] (show_stack) from [<c10b41f0>]
(dump_stack+0xb0/0xc4)
[ 4115.347480] [<c10b41f0>] (dump_stack) from [<c0349dc8>] (__warn+0xf8/0x110)
[ 4115.354406] [<c0349dc8>] (__warn) from [<c0349e24>]
(warn_slowpath_fmt+0x44/0x68)
[ 4115.361850] [<c0349e24>] (warn_slowpath_fmt) from [<c0b62918>]
(phylink_stop+0xd4/0xd8)
[ 4115.369813] [<c0b62918>] (phylink_stop) from [<c0bcc3c0>]
(stop_gfar+0x3c/0x48)
[ 4115.377085] [<c0bcc3c0>] (stop_gfar) from [<c0bccf68>] (reset_gfar+0x88/0xc8)
[ 4115.384185] [<c0bccf68>] (reset_gfar) from [<c03650d4>]
(process_one_work+0x218/0x510)
[ 4115.392062] [<c03650d4>] (process_one_work) from [<c0366544>]
(worker_thread+0x30/0x5a0)
[ 4115.400112] [<c0366544>] (worker_thread) from [<c036b33c>]
(kthread+0x120/0x150)
[ 4115.407469] [<c036b33c>] (kthread) from [<c03010e8>]
(ret_from_fork+0x14/0x2c)
[ 4115.414648] Exception stack(0xeaf8bfb0 to 0xeaf8bff8)
[ 4115.419668] bfa0:                                     00000000
00000000 00000000 00000000
[ 4115.427800] bfc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[ 4115.435932] bfe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 4115.442529] ---[ end trace c31a413a826ed6e0 ]---
[ 4115.447454] fsl-gianfar soc:ethernet@2d90000 eth2: Link is Down
[ 4115.457917] ------------[ cut here ]------------
[ 4115.462605] WARNING: CPU: 1 PID: 260 at
drivers/net/phy/phylink.c:952 phylink_start+0x1b4/0x270
[ 4115.471257] RTNL: assertion failed at drivers/net/phy/phylink.c (952)
[ 4115.477682] Modules linked in:
[ 4115.480725] CPU: 1 PID: 260 Comm: kworker/1:4 Tainted: G        W
      5.3.0-rc6-01275-g246284a4920a-dirty #251
[ 4115.491014] Hardware name: Freescale LS1021A
[ 4115.495263] Workqueue: events gfar_reset_task
[ 4115.499609] [<c03132e0>] (unwind_backtrace) from [<c030d8b8>]
(show_stack+0x10/0x14)
[ 4115.507315] [<c030d8b8>] (show_stack) from [<c10b41f0>]
(dump_stack+0xb0/0xc4)
[ 4115.514502] [<c10b41f0>] (dump_stack) from [<c0349dc8>] (__warn+0xf8/0x110)
[ 4115.521428] [<c0349dc8>] (__warn) from [<c0349e24>]
(warn_slowpath_fmt+0x44/0x68)
[ 4115.528872] [<c0349e24>] (warn_slowpath_fmt) from [<c0b61c9c>]
(phylink_start+0x1b4/0x270)
[ 4115.537094] [<c0b61c9c>] (phylink_start) from [<c0bcc994>]
(startup_gfar+0x248/0x2fc)
[ 4115.544885] [<c0bcc994>] (startup_gfar) from [<c0bccf70>]
(reset_gfar+0x90/0xc8)
[ 4115.552244] [<c0bccf70>] (reset_gfar) from [<c03650d4>]
(process_one_work+0x218/0x510)
[ 4115.560121] [<c03650d4>] (process_one_work) from [<c0366544>]
(worker_thread+0x30/0x5a0)
[ 4115.568171] [<c0366544>] (worker_thread) from [<c036b33c>]
(kthread+0x120/0x150)
[ 4115.575528] [<c036b33c>] (kthread) from [<c03010e8>]
(ret_from_fork+0x14/0x2c)
[ 4115.582708] Exception stack(0xeaf8bfb0 to 0xeaf8bff8)
[ 4115.587730] bfa0:                                     00000000
00000000 00000000 00000000
[ 4115.595862] bfc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[ 4115.603993] bfe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 4115.610607] ---[ end trace c31a413a826ed6e1 ]---

Hope this helps,
-Vladimir

^ permalink raw reply

* RE: [PATCH v1 net-next] net: phy: mdio_bus: make mdiobus_scan also cover PHY that only talks C45
From: Ong, Boon Leong @ 2019-08-28 15:41 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli
  Cc: David S. Miller, Maxime Coquelin, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Jose Abreu, Voon, Weifeng,
	Heiner Kallweit
In-Reply-To: <20190827154918.GO2168@lunn.ch>

>On Tue, Aug 27, 2019 at 03:23:34PM +0000, Voon, Weifeng wrote:
>> > > > Make mdiobus_scan() to try harder to look for any PHY that only
>> > talks C45.
>> > > If you are not using Device Tree or ACPI, and you are letting the MDIO
>> > > bus be scanned, it sounds like there should be a way for you to
>> > > provide a hint as to which addresses should be scanned (that's
>> > > mii_bus::phy_mask) and possibly enhance that with a mask of possible
>> > > C45 devices?
>> >
>> > Yes, i don't like this unconditional c45 scanning. A lot of MDIO bus
>> > drivers don't look for the MII_ADDR_C45. They are going to do a C22
>> > transfer, and maybe not mask out the MII_ADDR_C45 from reg, causing an
>> > invalid register write. Bad things can then happen.
>> >
>> > With DT and ACPI, we have an explicit indication that C45 should be used,
>> > so we know on this platform C45 is safe to use. We need something
>> > similar when not using DT or ACPI.
>> >
>> > 	  Andrew
>>
>> Florian and Andrew,
>> The mdio c22 is using the start-of-frame ST=01 while mdio c45 is using ST=00
>> as identifier. So mdio c22 device will not response to mdio c45 protocol.
>> As in IEEE 802.1ae-2002 Annex 45A.3 mention that:
>> " Even though the Clause 45 MDIO frames using the ST=00 frame code
>> will also be driven on to the Clause 22 MII Management interface,
>> the Clause 22 PHYs will ignore the frames. "
>>
>> Hence, I am not seeing any concern that the c45 scanning will mess up with
>> c22 devices.
>
>Hi Voon
>
>Take for example mdio-hisi-femac.c
>
>static int hisi_femac_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
>{
>        struct hisi_femac_mdio_data *data = bus->priv;
>        int ret;
>
>        ret = hisi_femac_mdio_wait_ready(data);
>        if (ret)
>                return ret;
>
>        writel((mii_id << BIT_PHY_ADDR_OFFSET) | regnum,
>               data->membase + MDIO_RWCTRL);
>
>
>There is no check here for MII_ADDR_C45. So it will perform a C22
>transfer. And regnum will still have MII_ADDR_C45 in it, so the
>writel() is going to set bit 30, since #define MII_ADDR_C45
>(1<<30). What happens on this hardware under these conditions?
>
>You cannot unconditionally ask an MDIO driver to do a C45
>transfer. Some drivers are going to do bad things.

Andrew & Florian, thanks for your review on this patch and insights on it.
We will look into the implementation as suggested as follow. 

- for each bit clear in mii_bus::phy_mask, scan it as C22
- for each bit clear in mii_bus::phy_c45_mask, scan it as C45

We will work on this and resubmit soonest. 

^ permalink raw reply

* [PATCH net-next 0/4] mlxsw: Various updates
From: Ido Schimmel @ 2019-08-28 15:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Patch #1 from Amit removes 56G speed support. The reasons for this are
detailed in the commit message.

Patch #2 from Shalom ensures that the hardware does not auto negotiate
the number of used lanes. For example, if a four lane port supports 100G
over both two and four lanes, it will not advertise the two lane link
mode.

Patch #3 bumps the firmware version supported by the driver.

Patch #4 from Petr adds ethtool counters to help debug the internal PTP
implementation in mlxsw. I copied Richard on this patch in case he has
comments.

Amit Cohen (1):
  mlxsw: Remove 56G speed support

Ido Schimmel (1):
  mlxsw: Bump firmware version to 13.2000.1886

Petr Machata (1):
  mlxsw: spectrum_ptp: Add counters for GC events

Shalom Toledo (1):
  mlxsw: spectrum: Prevent auto negotiation on number of lanes

 drivers/net/ethernet/mellanox/mlxsw/reg.h     |   1 -
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 140 ++++++++++++------
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  17 ++-
 .../ethernet/mellanox/mlxsw/spectrum_ptp.c    |  67 +++++++++
 .../ethernet/mellanox/mlxsw/spectrum_ptp.h    |  32 ++++
 .../net/ethernet/mellanox/mlxsw/switchx2.c    |   6 -
 6 files changed, 210 insertions(+), 53 deletions(-)

-- 
2.21.0


^ permalink raw reply

* [PATCH net-next 1/4] mlxsw: Remove 56G speed support
From: Ido Schimmel @ 2019-08-28 15:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, mlxsw, Amit Cohen, Ido Schimmel
In-Reply-To: <20190828155437.9852-1-idosch@idosch.org>

From: Amit Cohen <amitc@mellanox.com>

Commit 275e928f1911 ("mlxsw: spectrum: Prevent force of 56G") prevented
the driver from setting a speed of 56G when auto-negotiation is off.
This is the only speed supported by mlxsw that cannot be set when
auto-negotiation is off, which makes it difficult to write generic
tests.

Further, the speed is not supported by newer ASICs such as Spectrum-2
and to the best of our knowledge it is not used by current users.

Therefore, remove 56G support from mlxsw.

Signed-off-by: Amit Cohen <amitc@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h     |  1 -
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 24 -------------------
 .../net/ethernet/mellanox/mlxsw/switchx2.c    |  6 -----
 3 files changed, 31 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index baa20cdd65df..5494cf93f34c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -4126,7 +4126,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32);
 #define MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2		BIT(5)
 #define MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4		BIT(6)
 #define MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4		BIT(7)
-#define MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4		BIT(8)
 #define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR		BIT(12)
 #define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR		BIT(13)
 #define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR		BIT(14)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 7de9833fc60b..4d1f8b9c46a7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2608,26 +2608,6 @@ static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
 		.mask_ethtool	= ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
 		.speed		= SPEED_50000,
 	},
-	{
-		.mask		= MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
-		.mask_ethtool	= ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
-		.speed		= SPEED_56000,
-	},
-	{
-		.mask		= MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
-		.mask_ethtool	= ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
-		.speed		= SPEED_56000,
-	},
-	{
-		.mask		= MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
-		.mask_ethtool	= ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
-		.speed		= SPEED_56000,
-	},
-	{
-		.mask		= MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
-		.mask_ethtool	= ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
-		.speed		= SPEED_56000,
-	},
 	{
 		.mask		= MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
 		.mask_ethtool	= ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
@@ -3301,10 +3281,6 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
 	ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap, NULL, NULL);
 
 	autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
-	if (!autoneg && cmd->base.speed == SPEED_56000) {
-		netdev_err(dev, "56G not supported with autoneg off\n");
-		return -EINVAL;
-	}
 	eth_proto_new = autoneg ?
 		ops->to_ptys_advert_link(mlxsw_sp, cmd) :
 		ops->to_ptys_speed(mlxsw_sp, cmd->base.speed);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index bdab96f5bc70..1c14c051ee52 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -636,12 +636,6 @@ static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = {
 				  MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
 		.speed		= 50000,
 	},
-	{
-		.mask		= MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
-		.supported	= SUPPORTED_56000baseKR4_Full,
-		.advertised	= ADVERTISED_56000baseKR4_Full,
-		.speed		= 56000,
-	},
 	{
 		.mask		= MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
 				  MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
-- 
2.21.0


^ permalink raw reply related

* [PATCH net-next 2/4] mlxsw: spectrum: Prevent auto negotiation on number of lanes
From: Ido Schimmel @ 2019-08-28 15:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, mlxsw, Shalom Toledo, Ido Schimmel
In-Reply-To: <20190828155437.9852-1-idosch@idosch.org>

From: Shalom Toledo <shalomt@mellanox.com>

After 50G-1-lane and 100G-2-lanes link modes were introduced, the driver
is facing situations in which the hardware auto negotiates not only on
speed and type, but also on number of lanes.

Prevent auto negotiation on number of lanes by allowing only port speeds
that can be supported on a given port according to its width.

Signed-off-by: Shalom Toledo <shalomt@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 91 +++++++++++++++----
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  6 +-
 2 files changed, 77 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 4d1f8b9c46a7..d4e7971e525d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2655,7 +2655,7 @@ mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
 
 static void
 mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
-			 unsigned long *mode)
+			 u8 width, unsigned long *mode)
 {
 	int i;
 
@@ -2696,7 +2696,7 @@ mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
 }
 
 static u32
-mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
+mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
 			      const struct ethtool_link_ksettings *cmd)
 {
 	u32 ptys_proto = 0;
@@ -2710,7 +2710,8 @@ mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
 	return ptys_proto;
 }
 
-static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 speed)
+static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width,
+				   u32 speed)
 {
 	u32 ptys_proto = 0;
 	int i;
@@ -2898,11 +2899,31 @@ mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
 #define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
 	ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
 
+#define MLXSW_SP_PORT_MASK_WIDTH_1X	BIT(0)
+#define MLXSW_SP_PORT_MASK_WIDTH_2X	BIT(1)
+#define MLXSW_SP_PORT_MASK_WIDTH_4X	BIT(2)
+
+static u8 mlxsw_sp_port_mask_width_get(u8 width)
+{
+	switch (width) {
+	case 1:
+		return MLXSW_SP_PORT_MASK_WIDTH_1X;
+	case 2:
+		return MLXSW_SP_PORT_MASK_WIDTH_2X;
+	case 4:
+		return MLXSW_SP_PORT_MASK_WIDTH_4X;
+	default:
+		WARN_ON_ONCE(1);
+		return 0;
+	}
+}
+
 struct mlxsw_sp2_port_link_mode {
 	const enum ethtool_link_mode_bit_indices *mask_ethtool;
 	int m_ethtool_len;
 	u32 mask;
 	u32 speed;
+	u8 mask_width;
 };
 
 static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
@@ -2910,72 +2931,97 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_sgmii_100m,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X |
+				  MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_100,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_1000base_x_sgmii,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X |
+				  MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_1000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X |
+				  MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_2500,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_5gbase_r,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X |
+				  MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_5000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X |
+				  MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_10000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_40000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X |
+				  MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_25000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_2X |
+				  MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_50000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_1X,
 		.speed		= SPEED_50000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_100000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_2X,
 		.speed		= SPEED_100000,
 	},
 	{
 		.mask		= MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
 		.mask_ethtool	= mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
 		.m_ethtool_len	= MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
+		.mask_width	= MLXSW_SP_PORT_MASK_WIDTH_4X,
 		.speed		= SPEED_200000,
 	},
 };
@@ -3003,12 +3049,14 @@ mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
 
 static void
 mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
-			 unsigned long *mode)
+			 u8 width, unsigned long *mode)
 {
+	u8 mask_width = mlxsw_sp_port_mask_width_get(width);
 	int i;
 
 	for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
-		if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
+		if ((ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) &&
+		    (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
 			mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
 						  mode);
 	}
@@ -3059,27 +3107,32 @@ mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
 }
 
 static u32
-mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
+mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
 			      const struct ethtool_link_ksettings *cmd)
 {
+	u8 mask_width = mlxsw_sp_port_mask_width_get(width);
 	u32 ptys_proto = 0;
 	int i;
 
 	for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
-		if (mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
+		if ((mask_width & mlxsw_sp2_port_link_mode[i].mask_width) &&
+		    mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
 					       cmd->link_modes.advertising))
 			ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
 	}
 	return ptys_proto;
 }
 
-static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 speed)
+static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp,
+				   u8 width, u32 speed)
 {
+	u8 mask_width = mlxsw_sp_port_mask_width_get(width);
 	u32 ptys_proto = 0;
 	int i;
 
 	for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
-		if (speed == mlxsw_sp2_port_link_mode[i].speed)
+		if ((speed == mlxsw_sp2_port_link_mode[i].speed) &&
+		    (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
 			ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
 	}
 	return ptys_proto;
@@ -3163,7 +3216,7 @@ mlxsw_sp2_port_type_speed_ops = {
 
 static void
 mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
-				 struct ethtool_link_ksettings *cmd)
+				 u8 width, struct ethtool_link_ksettings *cmd)
 {
 	const struct mlxsw_sp_port_type_speed_ops *ops;
 
@@ -3174,12 +3227,13 @@ mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
 	ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
 
 	ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd);
-	ops->from_ptys_link(mlxsw_sp, eth_proto_cap, cmd->link_modes.supported);
+	ops->from_ptys_link(mlxsw_sp, eth_proto_cap, width,
+			    cmd->link_modes.supported);
 }
 
 static void
 mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
-				 u32 eth_proto_admin, bool autoneg,
+				 u32 eth_proto_admin, bool autoneg, u8 width,
 				 struct ethtool_link_ksettings *cmd)
 {
 	const struct mlxsw_sp_port_type_speed_ops *ops;
@@ -3190,7 +3244,7 @@ mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
 		return;
 
 	ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
-	ops->from_ptys_link(mlxsw_sp, eth_proto_admin,
+	ops->from_ptys_link(mlxsw_sp, eth_proto_admin, width,
 			    cmd->link_modes.advertising);
 }
 
@@ -3245,10 +3299,11 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
 	ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
 				 &eth_proto_admin, &eth_proto_oper);
 
-	mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap, cmd);
+	mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap,
+					 mlxsw_sp_port->mapping.width, cmd);
 
 	mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg,
-					 cmd);
+					 mlxsw_sp_port->mapping.width, cmd);
 
 	cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 	connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
@@ -3282,8 +3337,10 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
 
 	autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
 	eth_proto_new = autoneg ?
-		ops->to_ptys_advert_link(mlxsw_sp, cmd) :
-		ops->to_ptys_speed(mlxsw_sp, cmd->base.speed);
+		ops->to_ptys_advert_link(mlxsw_sp, mlxsw_sp_port->mapping.width,
+					 cmd) :
+		ops->to_ptys_speed(mlxsw_sp, mlxsw_sp_port->mapping.width,
+				   cmd->base.speed);
 
 	eth_proto_new = eth_proto_new & eth_proto_cap;
 	if (!eth_proto_new) {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 20c14bba9ccb..12f14a42b43a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -279,14 +279,14 @@ struct mlxsw_sp_port_type_speed_ops {
 					 u32 ptys_eth_proto,
 					 struct ethtool_link_ksettings *cmd);
 	void (*from_ptys_link)(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
-			       unsigned long *mode);
+			       u8 width, unsigned long *mode);
 	u32 (*from_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto);
 	void (*from_ptys_speed_duplex)(struct mlxsw_sp *mlxsw_sp,
 				       bool carrier_ok, u32 ptys_eth_proto,
 				       struct ethtool_link_ksettings *cmd);
-	u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp,
+	u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp, u8 width,
 				   const struct ethtool_link_ksettings *cmd);
-	u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u32 speed);
+	u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u8 width, u32 speed);
 	u32 (*to_ptys_upper_speed)(struct mlxsw_sp *mlxsw_sp, u32 upper_speed);
 	int (*port_speed_base)(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 			       u32 *base_speed);
-- 
2.21.0


^ permalink raw reply related

* [PATCH net-next 3/4] mlxsw: Bump firmware version to 13.2000.1886
From: Ido Schimmel @ 2019-08-28 15:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel
In-Reply-To: <20190828155437.9852-1-idosch@idosch.org>

From: Ido Schimmel <idosch@mellanox.com>

The new version supports extended error reporting from firmware via a
new TLV in the EMAD packet. Similar to netlink extended ack.

It also fixes an issue in the PCI code that can result in false AER
errors under high Tx rate.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index d4e7971e525d..dd3ae46e5eca 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -48,7 +48,7 @@
 
 #define MLXSW_SP1_FWREV_MAJOR 13
 #define MLXSW_SP1_FWREV_MINOR 2000
-#define MLXSW_SP1_FWREV_SUBMINOR 1122
+#define MLXSW_SP1_FWREV_SUBMINOR 1886
 #define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702
 
 static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
-- 
2.21.0


^ permalink raw reply related

* [PATCH net-next 4/4] mlxsw: spectrum_ptp: Add counters for GC events
From: Ido Schimmel @ 2019-08-28 15:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, jiri, mlxsw, Petr Machata, Richard Cochran, Ido Schimmel
In-Reply-To: <20190828155437.9852-1-idosch@idosch.org>

From: Petr Machata <petrm@mellanox.com>

On Spectrum-1, timestamped PTP packets and the corresponding timestamps need to
be kept in caches until both are available, at which point they are matched up
and packets forwarded as appropriate. However, not all packets will ever see
their timestamp, and not all timestamps will ever see their packet. It is
necessary to dispose of such abandoned entries, so a garbage collector was
introduced in commit 5d23e4159772 ("mlxsw: spectrum: PTP: Garbage-collect
unmatched entries").

If these GC events happen often, it is a sign of a problem. However because this
whole mechanism is taking place behind the scenes, there is no direct way to
determine whether garbage collection took place.

Therefore to fix this, on Spectrum-1 only, expose four artificial ethtool
counters for the GC events: GCd timestamps and packets, in TX and RX directions.

Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 23 ++++++-
 .../net/ethernet/mellanox/mlxsw/spectrum.h    | 11 +++
 .../ethernet/mellanox/mlxsw/spectrum_ptp.c    | 67 +++++++++++++++++++
 .../ethernet/mellanox/mlxsw/spectrum_ptp.h    | 32 +++++++++
 4 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index dd3ae46e5eca..91e4792bb7e7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -175,6 +175,10 @@ struct mlxsw_sp_ptp_ops {
 	void (*shaper_work)(struct work_struct *work);
 	int (*get_ts_info)(struct mlxsw_sp *mlxsw_sp,
 			   struct ethtool_ts_info *info);
+	int (*get_stats_count)(void);
+	void (*get_stats_strings)(u8 **p);
+	void (*get_stats)(struct mlxsw_sp_port *mlxsw_sp_port,
+			  u64 *data, int data_index);
 };
 
 static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
@@ -2329,6 +2333,7 @@ static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
 static void mlxsw_sp_port_get_strings(struct net_device *dev,
 				      u32 stringset, u8 *data)
 {
+	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
 	u8 *p = data;
 	int i;
 
@@ -2370,6 +2375,7 @@ static void mlxsw_sp_port_get_strings(struct net_device *dev,
 		for (i = 0; i < TC_MAX_QUEUE; i++)
 			mlxsw_sp_port_get_tc_strings(&p, i);
 
+		mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_strings(&p);
 		break;
 	}
 }
@@ -2464,6 +2470,7 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev,
 static void mlxsw_sp_port_get_stats(struct net_device *dev,
 				    struct ethtool_stats *stats, u64 *data)
 {
+	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
 	int i, data_index = 0;
 
 	/* IEEE 802.3 Counters */
@@ -2504,13 +2511,21 @@ static void mlxsw_sp_port_get_stats(struct net_device *dev,
 					  data, data_index);
 		data_index += MLXSW_SP_PORT_HW_TC_STATS_LEN;
 	}
+
+	/* PTP counters */
+	mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats(mlxsw_sp_port,
+						    data, data_index);
+	data_index += mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
 }
 
 static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
 {
+	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+
 	switch (sset) {
 	case ETH_SS_STATS:
-		return MLXSW_SP_PORT_ETHTOOL_STATS_LEN;
+		return MLXSW_SP_PORT_ETHTOOL_STATS_LEN +
+		       mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -4643,6 +4658,9 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
 	.hwtstamp_set	= mlxsw_sp1_ptp_hwtstamp_set,
 	.shaper_work	= mlxsw_sp1_ptp_shaper_work,
 	.get_ts_info	= mlxsw_sp1_ptp_get_ts_info,
+	.get_stats_count = mlxsw_sp1_get_stats_count,
+	.get_stats_strings = mlxsw_sp1_get_stats_strings,
+	.get_stats	= mlxsw_sp1_get_stats,
 };
 
 static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
@@ -4656,6 +4674,9 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
 	.hwtstamp_set	= mlxsw_sp2_ptp_hwtstamp_set,
 	.shaper_work	= mlxsw_sp2_ptp_shaper_work,
 	.get_ts_info	= mlxsw_sp2_ptp_get_ts_info,
+	.get_stats_count = mlxsw_sp2_get_stats_count,
+	.get_stats_strings = mlxsw_sp2_get_stats_strings,
+	.get_stats	= mlxsw_sp2_get_stats,
 };
 
 static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 12f14a42b43a..b2a0028b1694 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -225,6 +225,16 @@ struct mlxsw_sp_port_xstats {
 	u64 tx_packets[IEEE_8021QAZ_MAX_TCS];
 };
 
+struct mlxsw_sp_ptp_port_dir_stats {
+	u64 packets;
+	u64 timestamps;
+};
+
+struct mlxsw_sp_ptp_port_stats {
+	struct mlxsw_sp_ptp_port_dir_stats rx_gcd;
+	struct mlxsw_sp_ptp_port_dir_stats tx_gcd;
+};
+
 struct mlxsw_sp_port {
 	struct net_device *dev;
 	struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
@@ -271,6 +281,7 @@ struct mlxsw_sp_port {
 		struct hwtstamp_config hwtstamp_config;
 		u16 ing_types;
 		u16 egr_types;
+		struct mlxsw_sp_ptp_port_stats stats;
 	} ptp;
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index 38bb1cfe4e8c..ec2ff3d7f41c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -630,6 +630,8 @@ static void
 mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state,
 			    struct mlxsw_sp1_ptp_unmatched *unmatched)
 {
+	struct mlxsw_sp_ptp_port_dir_stats *stats;
+	struct mlxsw_sp_port *mlxsw_sp_port;
 	int err;
 
 	/* If an unmatched entry has an SKB, it has to be handed over to the
@@ -650,6 +652,17 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state,
 		/* The packet was matched with timestamp during the walk. */
 		goto out;
 
+	mlxsw_sp_port = ptp_state->mlxsw_sp->ports[unmatched->key.local_port];
+	if (mlxsw_sp_port) {
+		stats = unmatched->key.ingress ?
+			&mlxsw_sp_port->ptp.stats.rx_gcd :
+			&mlxsw_sp_port->ptp.stats.tx_gcd;
+		if (unmatched->skb)
+			stats->packets++;
+		else
+			stats->timestamps++;
+	}
+
 	/* mlxsw_sp1_ptp_unmatched_finish() invokes netif_receive_skb(). While
 	 * the comment at that function states that it can only be called in
 	 * soft IRQ context, this pattern of local_bh_disable() +
@@ -1098,3 +1111,57 @@ int mlxsw_sp1_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp,
 
 	return 0;
 }
+
+struct mlxsw_sp_ptp_port_stat {
+	char str[ETH_GSTRING_LEN];
+	ptrdiff_t offset;
+};
+
+#define MLXSW_SP_PTP_PORT_STAT(NAME, FIELD)				\
+	{								\
+		.str = NAME,						\
+		.offset = offsetof(struct mlxsw_sp_ptp_port_stats,	\
+				    FIELD),				\
+	}
+
+static const struct mlxsw_sp_ptp_port_stat mlxsw_sp_ptp_port_stats[] = {
+	MLXSW_SP_PTP_PORT_STAT("ptp_rx_gcd_packets",    rx_gcd.packets),
+	MLXSW_SP_PTP_PORT_STAT("ptp_rx_gcd_timestamps", rx_gcd.timestamps),
+	MLXSW_SP_PTP_PORT_STAT("ptp_tx_gcd_packets",    tx_gcd.packets),
+	MLXSW_SP_PTP_PORT_STAT("ptp_tx_gcd_timestamps", tx_gcd.timestamps),
+};
+
+#undef MLXSW_SP_PTP_PORT_STAT
+
+#define MLXSW_SP_PTP_PORT_STATS_LEN \
+	ARRAY_SIZE(mlxsw_sp_ptp_port_stats)
+
+int mlxsw_sp1_get_stats_count(void)
+{
+	return MLXSW_SP_PTP_PORT_STATS_LEN;
+}
+
+void mlxsw_sp1_get_stats_strings(u8 **p)
+{
+	int i;
+
+	for (i = 0; i < MLXSW_SP_PTP_PORT_STATS_LEN; i++) {
+		memcpy(*p, mlxsw_sp_ptp_port_stats[i].str,
+		       ETH_GSTRING_LEN);
+		*p += ETH_GSTRING_LEN;
+	}
+}
+
+void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port,
+			 u64 *data, int data_index)
+{
+	void *stats = &mlxsw_sp_port->ptp.stats;
+	ptrdiff_t offset;
+	int i;
+
+	data += data_index;
+	for (i = 0; i < MLXSW_SP_PTP_PORT_STATS_LEN; i++) {
+		offset = mlxsw_sp_ptp_port_stats[i].offset;
+		*data++ = *(u64 *)(stats + offset);
+	}
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
index 72e55f6926b9..8c386571afce 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
@@ -59,6 +59,11 @@ void mlxsw_sp1_ptp_shaper_work(struct work_struct *work);
 int mlxsw_sp1_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp,
 			      struct ethtool_ts_info *info);
 
+int mlxsw_sp1_get_stats_count(void);
+void mlxsw_sp1_get_stats_strings(u8 **p);
+void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port,
+			 u64 *data, int data_index);
+
 #else
 
 static inline struct mlxsw_sp_ptp_clock *
@@ -125,6 +130,19 @@ static inline int mlxsw_sp1_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp,
 	return mlxsw_sp_ptp_get_ts_info_noptp(info);
 }
 
+static inline int mlxsw_sp1_get_stats_count(void)
+{
+	return 0;
+}
+
+static inline void mlxsw_sp1_get_stats_strings(u8 **p)
+{
+}
+
+static inline void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port,
+				       u64 *data, int data_index)
+{
+}
 #endif
 
 static inline struct mlxsw_sp_ptp_clock *
@@ -183,4 +201,18 @@ static inline int mlxsw_sp2_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp,
 	return mlxsw_sp_ptp_get_ts_info_noptp(info);
 }
 
+static inline int mlxsw_sp2_get_stats_count(void)
+{
+	return 0;
+}
+
+static inline void mlxsw_sp2_get_stats_strings(u8 **p)
+{
+}
+
+static inline void mlxsw_sp2_get_stats(struct mlxsw_sp_port *mlxsw_sp_port,
+				       u64 *data, int data_index)
+{
+}
+
 #endif
-- 
2.21.0


^ permalink raw reply related

* RE: [E1000-devel] SFP+ EEPROM readouts fail on X722 (ethtool -m: Invalid argument)
From: Buchholz, Donald @ 2019-08-28 16:12 UTC (permalink / raw)
  To: Jakub Jankowski, Fujinaka, Todd,
	e1000-devel@lists.sourceforge.net
  Cc: netdev@vger.kernel.org, mhemsley@open-systems.com, Yang, Lihong
In-Reply-To: <1277a516-78ac-8bcd-64ac-d97a260451bc@toxcorp.com>

Hi Jakub,

That commit was for "ethtool -e" and not "ethtool -m".

There was some firmware support required to implement "ethtool -m"
missing in original X722 NVM images that, ttbomk, still was not
present in early 2019.  My situation is similar to Todd's -- we
know a request to add this support has been submitted, but are
not clear if it has been approved, completed, or shipped yet.

- Don



> -----Original Message-----
> From: Jakub Jankowski [mailto:shasta@toxcorp.com]
> Sent: Wednesday, August 28, 2019 12:18 AM
> To: Fujinaka, Todd <todd.fujinaka@intel.com>; e1000-
> devel@lists.sourceforge.net
> Cc: netdev@vger.kernel.org; mhemsley@open-systems.com; Yang, Lihong
> <lihong.yang@intel.com>
> Subject: Re: [E1000-devel] SFP+ EEPROM readouts fail on X722 (ethtool -m:
> Invalid argument)
> 
> This commit suggests that it should be possible:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/
> ?id=c271dd6c391b535226cf1a81aaad9f33cb5899d3
> (It has been in upstream kernel since v4.12, so my test kernel does have
> it, and so does the out-of-tree driver I'm testing with)
> 
> On 8/28/19 2:53 AM, Fujinaka, Todd wrote:
> > Sorry about the top posting, but if I don't do it this way I can't read
> anything in Outlook (not my preferred MUA).
> >
> > I think I may have been wrong about things. I'm not as familiar with the
> x722, and the NVM versions are completely different than the x710 and I
> was confused.
> >
> > Even worse, I'm not sure if the x722 is able to read the data from the
> SFP/SFP+ EEPROM. I remembered that was a feature we requested internally
> but I don't remember what the progress was.
> >
> > I'm asking around to see if I can get clarification. I haven't heard
> anything yet.
> >
> > Todd Fujinaka
> > Software Application Engineer
> > Datacenter Engineering Group
> > Intel Corporation
> > todd.fujinaka@intel.com
> >
> >
> > -----Original Message-----
> > From: Jakub Jankowski [mailto:shasta@toxcorp.com]
> > Sent: Tuesday, August 27, 2019 4:01 PM
> > To: Fujinaka, Todd <todd.fujinaka@intel.com>; e1000-
> devel@lists.sourceforge.net
> > Cc: netdev@vger.kernel.org; mhemsley@open-systems.com
> > Subject: Re: [E1000-devel] SFP+ EEPROM readouts fail on X722 (ethtool -
> m: Invalid argument)
> >
> > Hi,
> >
> > On 8/27/19 7:56 PM, Fujinaka, Todd wrote:
> >> The hints should be:
> >> # ethtool -m eth10
> >> Cannot get module EEPROM information: Invalid argument # dmesg | tail -
> n 1 [  445.971974] i40e 0000:3d:00.3 eth10: Module EEPROM memory read not
> supported. Please update the NVM image.
> >>
> >> # ethtool -i eth10
> >> driver: i40e
> >> version: 2.9.21
> >> firmware-version: 3.31 0x80000d31 1.1767.0
> >>
> >> And the working case:
> >> # ethtool -i eth8
> >> driver: i40e
> >> version: 2.9.21
> >> firmware-version: 6.01 0x800035cf 1.1876.0
> >>
> >> If you don't see it, 6.01 > 3.31.
> > The reason why firmware between the two is (that much) different is
> because the non-working case is from X722 NIC, while the working one is
> from X710.
> >
> >> The NVM update tool should be available on downloadcenter.intel.com
> > Thanks for the pointer to NVM updater. I'd like to offer some additional
> comments about my experience with the newest one (v4.00):
> >
> > a) running ./nvmupdate64e (from X722_NVMUpdate_Linux_x64 subdir) errors
> out without really saying what's wrong:
> >
> >     # ./nvmupdate64e
> >
> >     Intel(R) Ethernet NVM Update Tool
> >     NVMUpdate version 1.30.2.11
> >     Copyright (C) 2013 - 2017 Intel Corporation.
> >
> >
> >     WARNING: To avoid damage to your device, do not stop the update or
> reboot or power off the system during this update.
> >     Inventory in progress. Please wait [+.........]
> >     Tool execution completed with the following status: The
> configuration file could not be opened/read, or a syntax error was
> discovered in the file
> >     Press any key to exit.
> >
> > after enabling logging (-l out.log) a bit more is revealed:
> >
> >     # tail -n 2 out.log
> >     Error:   Config file line 2: Not supported config file version.
> >     Error:   Missing CONFIG VERSION parameter in configuration file.
> >
> > but that's not entirely true, CONFIG VERSION is set in the default
> configuration file:
> >
> >     # head -n 2 nvmupdate.cfg
> >     CURRENT FAMILY: 1.0.0
> >     CONFIG VERSION: 1.14.0
> >
> > so why isn't this understood?
> > Manually editing nvmupdate.cfg and setting CONFIG VERSION: 1.11.0 seems
> to make this particular problem go away.
> >
> > b) Re-doing this with downgraded config version exposes another problem:
> >
> >     Config file read.
> >     Error:   Can't open NVM map file [Immediate_offset_2.txt]
> >
> > and indeed, there is no Immediate_offset_2.txt in
> NVMUpdatePackage_WFT_WFQ&WF0_v4.00/X722_NVMUpdate_Linux_x64/
> > There is one, however, in
> > NVMUpdatePackage_WFT_WFQ&WF0_v4.00/X722_NVMUpdate_EFIx64/ subdir.
> > Copying it over to the _Linux_x64 resolves this particular problem
> >
> > c) Re-doing this with Immediate_offset_2.txt in place exposes third
> problem:
> >
> >     Error:   Can't open NVM image file
> >
> [LBG_B2_Wolf_Pass_WFT_X557_P01_PHY_Auto_Detect_P23_NCSI_v3.31_800016DB.bin
> ]
> >
> > and once again - same story. It exists in
> NVMUpdatePackage_WFT_WFQ&WF0_v4.00/X722_NVMUpdate_EFIx64/ but not
> NVMUpdatePackage_WFT_WFQ&WF0_v4.00/X722_NVMUpdate_Linux_x64/ - had to copy
> it over.
> >
> >
> > Once I managed to get all these out of the way, the tool finally ran:
> >
> >     Num Description                               Ver. DevId S:B Status
> >     === ======================================== ===== ===== ======
> ===============
> >     01) Intel(R) Ethernet Server Adapter I350-T4  1.99  1521 00:024
> Update not available
> >     02) Intel(R) Ethernet Connection X722 for     3.49  37D2 00:061
> Update
> >         10GBASE-T available
> >     03) Intel(R) Ethernet Server Adapter I350-T4  1.99  1521 00:175
> Update not available
> >
> >
> > The initial starting point was:
> >
> > 0) firmware-version: 3.31 0x80000d31 1.1767.0
> >
> > After first update+reboot, this was bumped to:
> >
> > 1) firmware-version: 3.1d 0x800016db 1.1767.0    (but ethtool -m ethX
> still doesn't work)
> >
> > So I ran the tool the second time, it said 'Update available' again, but
> this time:
> >
> >     Num Description                               Ver. DevId S:B Status
> >     === ======================================== ===== ===== ======
> ===============
> >     01) Intel(R) Ethernet Server Adapter I350-T4  1.99  1521 00:024
> Update not available
> >     02) Intel(R) Ethernet Connection X722 for     3.29  37D2 00:061
> Update
> >         10GBASE-T available
> >     03) Intel(R) Ethernet Server Adapter I350-T4  1.99  1521 00:175
> Update not available
> >
> >     Options: Adapter Index List (comma-separated), [A]ll, e[X]it
> >     Enter selection:02
> >     Would you like to back up the NVM images? [Y]es/[N]o: Y
> >     Update in progress. This operation may take several minutes.
> >     [*******+..]
> >     Tool execution completed with the following status: <---------- why
> is there no status printed?
> >     Press any key to exit.
> >
> >
> > Checking output log:
> >
> >     # cat out3.log
> >     Intel(R) Ethernet NVM Update Tool
> >     NVMUpdate version 1.30.2.11
> >     Copyright (C) 2013 - 2017 Intel Corporation.
> >
> >     ./nvmupdate64e -c nvmupdate.cfg -l out3.log
> >
> >     Config file read.
> >     Inventory
> >     [00:061:00:00]: Intel(R) Ethernet Connection X722 for 10GBASE-T
> >         Flash inventory started
> >         Shadow RAM inventory started
> >     Alternate MAC address is not set
> >         Shadow RAM inventory finished
> >         Flash inventory finished
> >         OROM inventory started
> >         OROM inventory finished
> >         PHY NVM inventory started
> >         PHY NVM inventory finished
> >     [00:061:00:01]: Intel(R) Ethernet Connection X722 for 10GBASE-T
> >         Device already inventoried.
> >     [00:061:00:02]: Intel(R) Ethernet Connection X722 for 10GbE SFP+
> >         Device already inventoried.
> >         PHY NVM inventory started
> >         PHY NVM inventory finished
> >     [00:061:00:03]: Intel(R) Ethernet Connection X722 for 10GbE SFP+
> >         Device already inventoried.
> >     Update
> >     [00:061:00:00]: Intel(R) Ethernet Connection X722 for 10GBASE-T
> >         Creating backup images in directory: A4BF0164884A
> >         Backup images created.
> >         Flash update started
> >         NVM image verification started
> >         Shadow RAM image verification started
> >
> >     Image differences found at offset 0x3AE [Device=0xF, Buffer=0x0] -
> > update required.
> >     Error:   Flash update failed
> >     [00:061:00:02]: Intel(R) Ethernet Connection X722 for 10GbE SFP+
> >     #
> >
> > However, ethtool -i suggests that firmware was updated to:
> >
> > 2) firmware-version: 4.00 0x80001577 1.1580.0    <------- so it did
> > _something_ after all?
> >
> > At this point, every subsequent attempt to run the NVM updater yields
> > the same results: an update is available, but attempting to apply it
> > fails with the same message in log.
> >
> > And my initial issue still persists - ethtool -m <iface> still returns
> > "invalid argument" with "Module EEPROM memory read not supported. Please
> > update the NVM image" logged in dmesg.
> >
> > How can I resolve this?
> >
> > Cheers,
> >    Jakub.
> >
> >> Todd Fujinaka
> >> Software Application Engineer
> >> Datacenter Engineering Group
> >> Intel Corporation
> >> todd.fujinaka@intel.com
> >>
> >>
> >> -----Original Message-----
> >> From: Jakub Jankowski [mailto:shasta@toxcorp.com]
> >> Sent: Tuesday, August 27, 2019 4:03 AM
> >> To: e1000-devel@lists.sourceforge.net
> >> Cc: netdev@vger.kernel.org; shasta@toxcorp.com; mhemsley@open-
> systems.com
> >> Subject: [E1000-devel] SFP+ EEPROM readouts fail on X722 (ethtool -m:
> Invalid argument)
> >>
> >> Hi,
> >>
> >> We can't get SFP+ EEPROM readouts for X722 to work at all:
> >>
> >> # ethtool -m eth10
> >> Cannot get module EEPROM information: Invalid argument # dmesg | tail -
> n 1 [  445.971974] i40e 0000:3d:00.3 eth10: Module EEPROM memory read not
> supported. Please update the NVM image.
> >> # lspci | grep 3d:00.3
> >> 3d:00.3 Ethernet controller: Intel Corporation Ethernet Connection X722
> for 10GbE SFP+ (rev 09)
> >>
> >>
> >> We're running 4.19.65 kernel at the moment, testing using the newest
> out-of-tree Intel module
> >>
> >> # modinfo -F version i40e
> >> 2.9.21
> >>
> >> We also tried:
> >> - 4.19.65 with in-tree i40e (2.3.2-k)
> >> - stock Arch Linux (kernel 5.2.5, driver 2.8.20-k) and the results are
> the same, as shown above.
> >>
> >> # ethtool -i eth10
> >> driver: i40e
> >> version: 2.9.21
> >> firmware-version: 3.31 0x80000d31 1.1767.0
> >> expansion-rom-version:
> >> bus-info: 0000:3d:00.3
> >> supports-statistics: yes
> >> supports-test: yes
> >> supports-eeprom-access: yes
> >> supports-register-dump: yes
> >> supports-priv-flags: yes
> >> # dmidecode -s baseboard-manufacturer
> >> Intel Corporation
> >> # dmidecode -s baseboard-product-name
> >> S2600WFT
> >> # dmidecode -s baseboard-version
> >> H48104-853
> >>
> >> # lspci -vvv
> >> (...)
> >> 3d:00.3 Ethernet controller: Intel Corporation Ethernet Connection X722
> for 10GbE SFP+ (rev 09)
> >> 	DeviceName: Intel PCH Integrated 10 Gigabit Ethernet Controller
> >> 	Subsystem: Intel Corporation Ethernet Connection X722 for 10GbE SFP+
> >> 	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+
> Stepping- SERR+ FastB2B- DisINTx+
> >> 	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
> <TAbort- <MAbort- >SERR- <PERR- INTx-
> >> 	Latency: 0, Cache Line Size: 32 bytes
> >> 	Interrupt: pin A routed to IRQ 112
> >> 	NUMA node: 0
> >> 	Region 0: Memory at ab000000 (64-bit, prefetchable) [size=16M]
> >> 	Region 3: Memory at b0000000 (64-bit, prefetchable) [size=32K]
> >> 	Expansion ROM at <ignored> [disabled]
> >> 	Capabilities: [40] Power Management version 3
> >> 		Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-
> ,D3hot+,D3cold+)
> >> 		Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=1 PME-
> >> 	Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
> >> 		Address: 0000000000000000  Data: 0000
> >> 		Masking: 00000000  Pending: 00000000
> >> 	Capabilities: [70] MSI-X: Enable+ Count=129 Masked-
> >> 		Vector table: BAR=3 offset=00000000
> >> 		PBA: BAR=3 offset=00001000
> >> 	Capabilities: [a0] Express (v2) Endpoint, MSI 00
> >> 		DevCap:	MaxPayload 512 bytes, PhantFunc 0, Latency L0s
> <512ns, L1 <64us
> >> 			ExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
> SlotPowerLimit 0.000W
> >> 		DevCtl:	CorrErr+ NonFatalErr+ FatalErr+ UnsupReq+
> >> 			RlxdOrd+ ExtTag+ PhantFunc- AuxPwr- NoSnoop- FLReset-
> >> 			MaxPayload 256 bytes, MaxReadReq 512 bytes
> >> 		DevSta:	CorrErr+ NonFatalErr- FatalErr- UnsupReq+ AuxPwr+
> TransPend-
> >> 		LnkCap:	Port #0, Speed 2.5GT/s, Width x1, ASPM L0s L1,
> Exit Latency L0s <64ns, L1 <1us
> >> 			ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp+
> >> 		LnkCtl:	ASPM Disabled; RCB 64 bytes Disabled- CommClk+
> >> 			ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
> >> 		LnkSta:	Speed 2.5GT/s (ok), Width x1 (ok)
> >> 			TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
> >> 		DevCap2: Completion Timeout: Range AB, TimeoutDis+, LTR-, OBFF
> Not Supported
> >> 			 AtomicOpsCap: 32bit- 64bit- 128bitCAS-
> >> 		DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-,
> OBFF Disabled
> >> 			 AtomicOpsCtl: ReqEn-
> >> 		LnkSta2: Current De-emphasis Level: -6dB,
> EqualizationComplete-, EqualizationPhase1-
> >> 			 EqualizationPhase2-, EqualizationPhase3-,
> LinkEqualizationRequest-
> >> 	Capabilities: [e0] Vital Product Data
> >> 		Product Name: Example VPD
> >> 		Read-only fields:
> >> 			[V0] Vendor specific:
> >> 			[RV] Reserved: checksum good, 0 byte(s) reserved
> >> 		End
> >> 	Capabilities: [100 v2] Advanced Error Reporting
> >> 		UESta:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
> RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
> >> 		UEMsk:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
> RxOF- MalfTLP- ECRC- UnsupReq+ ACSViol-
> >> 		UESvrt:	DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt-
> RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
> >> 		CESta:	RxErr- BadTLP- BadDLLP- Rollover- Timeout-
> AdvNonFatalErr+
> >> 		CEMsk:	RxErr- BadTLP- BadDLLP- Rollover- Timeout-
> AdvNonFatalErr+
> >> 		AERCap:	First Error Pointer: 00, ECRCGenCap+ ECRCGenEn-
> ECRCChkCap+ ECRCChkEn-
> >> 			MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
> >> 		HeaderLog: 00000000 00000000 00000000 00000000
> >> 	Capabilities: [150 v1] Alternative Routing-ID Interpretation (ARI)
> >> 		ARICap:	MFVC- ACS-, Next Function: 0
> >> 		ARICtl:	MFVC- ACS-, Function Group: 0
> >> 	Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
> >> 		IOVCap:	Migration-, Interrupt Message Number: 000
> >> 		IOVCtl:	Enable- Migration- Interrupt- MSE- ARIHierarchy-
> >> 		IOVSta:	Migration-
> >> 		Initial VFs: 32, Total VFs: 32, Number of VFs: 0, Function
> Dependency Link: 03
> >> 		VF offset: 109, stride: 1, Device ID: 37cd
> >> 		Supported Page Size: 00000553, System Page Size: 00000001
> >> 		Region 0: Memory at 00000000af000000 (64-bit, prefetchable)
> >> 		Region 3: Memory at 00000000b0020000 (64-bit, prefetchable)
> >> 		VF Migration: offset: 00000000, BIR: 0
> >> 	Capabilities: [1a0 v1] Transaction Processing Hints
> >> 		Device specific mode supported
> >> 		No steering table available
> >> 	Capabilities: [1b0 v1] Access Control Services
> >> 		ACSCap:	SrcValid- TransBlk- ReqRedir- CmpltRedir-
> UpstreamFwd- EgressCtrl- DirectTrans-
> >> 		ACSCtl:	SrcValid- TransBlk- ReqRedir- CmpltRedir-
> UpstreamFwd- EgressCtrl- DirectTrans-
> >> 	Kernel driver in use: i40e
> >> 	Kernel modules: i40e
> >>
> >>
> >> Same kernel+i40e, same SFP+ module - but on Intel X710, works like a
> treat:
> >>
> >> # lspci | grep X7
> >> 81:00.0 Ethernet controller: Intel Corporation Ethernet Controller X710
> for 10GbE SFP+ (rev 01)
> >> 81:00.1 Ethernet controller: Intel Corporation Ethernet Controller X710
> for 10GbE SFP+ (rev 01) # ethtool -m eth8
> >> 	Identifier                                : 0x03 (SFP)
> >> 	Extended identifier                       : 0x04 (GBIC/SFP defined
> by 2-wire interface ID)
> >> 	Connector                                 : 0x07 (LC)
> >> 	Transceiver codes                         : 0x10 0x00 0x00 0x01 0x00
> 0x00 0x00 0x00 0x00
> >> 	Transceiver type                          : 10G Ethernet: 10G Base-
> SR
> >> 	Transceiver type                          : Ethernet: 1000BASE-SX
> >> 	Encoding                                  : 0x06 (64B/66B)
> >> 	BR, Nominal                               : 10300MBd
> >>            (...)
> >> # ethtool -i eth8
> >> driver: i40e
> >> version: 2.9.21
> >> firmware-version: 6.01 0x800035cf 1.1876.0
> >> expansion-rom-version:
> >> bus-info: 0000:81:00.0
> >> supports-statistics: yes
> >> supports-test: yes
> >> supports-eeprom-access: yes
> >> supports-register-dump: yes
> >> supports-priv-flags: yes
> >> #
> >>
> >>
> >> Is this a known problem?
> >>
> >>
> >> Best regards,
> >>     Jakub
> >>
> >>
> >>
> >> _______________________________________________
> >> E1000-devel mailing list
> >> E1000-devel@lists.sourceforge.net
> >> https://lists.sourceforge.net/lists/listinfo/e1000-devel
> >> To learn more about Intel&#174; Ethernet, visit
> http://communities.intel.com/community/wired
> 
> 
> --
> Jakub Jankowski|shasta@toxcorp.com|http://toxcorp.com/
> GPG: FCBF F03D 9ADB B768 8B92 BB52 0341 9037 A875 942D
> 
> 
> 
> _______________________________________________
> E1000-devel mailing list
> E1000-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/e1000-devel
> To learn more about Intel&#174; Ethernet, visit
> http://communities.intel.com/community/wired

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox