Commit 3dff4c62 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hns3-new-features'



Peng Li says:

====================
add some features to hns3 driver

This patchset adds some features to hns3 driver, include the support
for ethtool command -d, -p and support for manager table.

[Patch 1/4] adds support for ethtool command -d, its ops is get_regs.
driver will send command to command queue, and get regs number and
regs value from command queue.
[Patch 2/4] adds manager table initialization for hardware.
[Patch 3/4] adds support for ethtool command -p. For fiber ports, driver
sends command to command queue, and IMP will write SGPIO regs to control
leds.
[Patch 4/4] adds support for net status led for fiber ports. Net status
include  port speed, total rx/tx packets and link status. Driver send
the status to command queue, and IMP will write SGPIO to control leds.

---
Change log:
V1 -> V2:
1, fix comments from Andrew Lunn, remove the patch "net: hns3: add
ethtool -p support for phy device".
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b2d3bcfa 716aaac1
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -356,7 +356,8 @@ struct hnae3_ae_ops {
			    u32 stringset, u8 *data);
	int (*get_sset_count)(struct hnae3_handle *handle, int stringset);

	void (*get_regs)(struct hnae3_handle *handle, void *data);
	void (*get_regs)(struct hnae3_handle *handle, u32 *version,
			 void *data);
	int (*get_regs_len)(struct hnae3_handle *handle);

	u32 (*get_rss_key_size)(struct hnae3_handle *handle);
@@ -404,6 +405,8 @@ struct hnae3_ae_ops {
	int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num);
	void (*get_flowctrl_adv)(struct hnae3_handle *handle,
				 u32 *flowctrl_adv);
	int (*set_led_id)(struct hnae3_handle *handle,
			  enum ethtool_phys_id_state status);
};

struct hnae3_dcb_ops {
+35 −0
Original line number Diff line number Diff line
@@ -1063,6 +1063,38 @@ static int hns3_set_coalesce(struct net_device *netdev,
	return 0;
}

static int hns3_get_regs_len(struct net_device *netdev)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);

	if (!h->ae_algo->ops->get_regs_len)
		return -EOPNOTSUPP;

	return h->ae_algo->ops->get_regs_len(h);
}

static void hns3_get_regs(struct net_device *netdev,
			  struct ethtool_regs *cmd, void *data)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);

	if (!h->ae_algo->ops->get_regs)
		return;

	h->ae_algo->ops->get_regs(h, &cmd->version, data);
}

static int hns3_set_phys_id(struct net_device *netdev,
			    enum ethtool_phys_id_state state)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);

	if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_led_id)
		return -EOPNOTSUPP;

	return h->ae_algo->ops->set_led_id(h, state);
}

static const struct ethtool_ops hns3vf_ethtool_ops = {
	.get_drvinfo = hns3_get_drvinfo,
	.get_ringparam = hns3_get_ringparam,
@@ -1103,6 +1135,9 @@ static const struct ethtool_ops hns3_ethtool_ops = {
	.set_channels = hns3_set_channels,
	.get_coalesce = hns3_get_coalesce,
	.set_coalesce = hns3_set_coalesce,
	.get_regs_len = hns3_get_regs_len,
	.get_regs = hns3_get_regs,
	.set_phys_id = hns3_set_phys_id,
};

void hns3_ethtool_set_ops(struct net_device *netdev)
+47 −0
Original line number Diff line number Diff line
@@ -102,6 +102,10 @@ enum hclge_opcode_type {
	HCLGE_OPC_STATS_64_BIT		= 0x0030,
	HCLGE_OPC_STATS_32_BIT		= 0x0031,
	HCLGE_OPC_STATS_MAC		= 0x0032,

	HCLGE_OPC_QUERY_REG_NUM		= 0x0040,
	HCLGE_OPC_QUERY_32_BIT_REG	= 0x0041,
	HCLGE_OPC_QUERY_64_BIT_REG	= 0x0042,
	/* Device management command */

	/* MAC commond */
@@ -111,6 +115,7 @@ enum hclge_opcode_type {
	HCLGE_OPC_QUERY_LINK_STATUS	= 0x0307,
	HCLGE_OPC_CONFIG_MAX_FRM_SIZE	= 0x0308,
	HCLGE_OPC_CONFIG_SPEED_DUP	= 0x0309,
	HCLGE_OPC_STATS_MAC_TRAFFIC	= 0x0314,
	/* MACSEC command */

	/* PFC/Pause CMD*/
@@ -223,6 +228,9 @@ enum hclge_opcode_type {

	/* Mailbox cmd */
	HCLGEVF_OPC_MBX_PF_TO_VF	= 0x2000,

	/* Led command */
	HCLGE_OPC_LED_STATUS_CFG	= 0xB000,
};

#define HCLGE_TQP_REG_OFFSET		0x80000
@@ -601,6 +609,28 @@ struct hclge_mac_vlan_mask_entry_cmd {
	u8 rsv2[14];
};

#define HCLGE_MAC_MGR_MASK_VLAN_B		BIT(0)
#define HCLGE_MAC_MGR_MASK_MAC_B		BIT(1)
#define HCLGE_MAC_MGR_MASK_ETHERTYPE_B		BIT(2)
#define HCLGE_MAC_ETHERTYPE_LLDP		0x88cc

struct hclge_mac_mgr_tbl_entry_cmd {
	u8      flags;
	u8      resp_code;
	__le16  vlan_tag;
	__le32  mac_addr_hi32;
	__le16  mac_addr_lo16;
	__le16  rsv1;
	__le16  ethter_type;
	__le16  egress_port;
	__le16  egress_queue;
	u8      sw_port_id_aware;
	u8      rsv2;
	u8      i_port_bitmap;
	u8      i_port_direction;
	u8      rsv3[2];
};

#define HCLGE_CFG_MTA_MAC_SEL_S		0x0
#define HCLGE_CFG_MTA_MAC_SEL_M		GENMASK(1, 0)
#define HCLGE_CFG_MTA_MAC_EN_B		0x7
@@ -781,6 +811,23 @@ struct hclge_reset_cmd {
#define HCLGE_NIC_CMQ_DESC_NUM		1024
#define HCLGE_NIC_CMQ_DESC_NUM_S	3

#define HCLGE_LED_PORT_SPEED_STATE_S	0
#define HCLGE_LED_PORT_SPEED_STATE_M	GENMASK(5, 0)
#define HCLGE_LED_ACTIVITY_STATE_S	0
#define HCLGE_LED_ACTIVITY_STATE_M	GENMASK(1, 0)
#define HCLGE_LED_LINK_STATE_S		0
#define HCLGE_LED_LINK_STATE_M		GENMASK(1, 0)
#define HCLGE_LED_LOCATE_STATE_S	0
#define HCLGE_LED_LOCATE_STATE_M	GENMASK(1, 0)

struct hclge_set_led_state_cmd {
	u8 port_speed_led_config;
	u8 link_led_config;
	u8 activity_led_config;
	u8 locate_led_config;
	u8 rsv[20];
};

int hclge_cmd_init(struct hclge_dev *hdev);
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
{
+456 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ static int hclge_set_mta_filter_mode(struct hclge_dev *hdev,
static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu);
static int hclge_init_vlan_config(struct hclge_dev *hdev);
static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev);
static int hclge_update_led_status(struct hclge_dev *hdev);

static struct hnae3_ae_algo ae_algo;

@@ -392,6 +393,16 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = {
		HCLGE_MAC_STATS_FIELD_OFF(mac_rx_send_app_bad_pkt_num)}
};

static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = {
	{
		.flags = HCLGE_MAC_MGR_MASK_VLAN_B,
		.ethter_type = cpu_to_le16(HCLGE_MAC_ETHERTYPE_LLDP),
		.mac_addr_hi32 = cpu_to_le32(htonl(0x0180C200)),
		.mac_addr_lo16 = cpu_to_le16(htons(0x000E)),
		.i_port_bitmap = 0x1,
	},
};

static int hclge_64_bit_update_stats(struct hclge_dev *hdev)
{
#define HCLGE_64_BIT_CMD_NUM 5
@@ -495,6 +506,38 @@ static int hclge_32_bit_update_stats(struct hclge_dev *hdev)
	return 0;
}

static int hclge_mac_get_traffic_stats(struct hclge_dev *hdev)
{
	struct hclge_mac_stats *mac_stats = &hdev->hw_stats.mac_stats;
	struct hclge_desc desc;
	__le64 *desc_data;
	int ret;

	/* for fiber port, need to query the total rx/tx packets statstics,
	 * used for data transferring checking.
	 */
	if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_FIBER)
		return 0;

	if (test_bit(HCLGE_STATE_STATISTICS_UPDATING, &hdev->state))
		return 0;

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_STATS_MAC_TRAFFIC, true);
	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Get MAC total pkt stats fail, ret = %d\n", ret);

		return ret;
	}

	desc_data = (__le64 *)(&desc.data[0]);
	mac_stats->mac_tx_total_pkt_num += le64_to_cpu(*desc_data++);
	mac_stats->mac_rx_total_pkt_num += le64_to_cpu(*desc_data);

	return 0;
}

static int hclge_mac_update_stats(struct hclge_dev *hdev)
{
#define HCLGE_MAC_CMD_NUM 21
@@ -2836,13 +2879,20 @@ static void hclge_service_task(struct work_struct *work)
	struct hclge_dev *hdev =
		container_of(work, struct hclge_dev, service_task);

	/* The total rx/tx packets statstics are wanted to be updated
	 * per second. Both hclge_update_stats_for_all() and
	 * hclge_mac_get_traffic_stats() can do it.
	 */
	if (hdev->hw_stats.stats_timer >= HCLGE_STATS_TIMER_INTERVAL) {
		hclge_update_stats_for_all(hdev);
		hdev->hw_stats.stats_timer = 0;
	} else {
		hclge_mac_get_traffic_stats(hdev);
	}

	hclge_update_speed_duplex(hdev);
	hclge_update_link_status(hdev);
	hclge_update_led_status(hdev);
	hclge_service_complete(hdev);
}

@@ -4249,6 +4299,91 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
	return status;
}

static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev,
					      u16 cmdq_resp, u8 resp_code)
{
#define HCLGE_ETHERTYPE_SUCCESS_ADD		0
#define HCLGE_ETHERTYPE_ALREADY_ADD		1
#define HCLGE_ETHERTYPE_MGR_TBL_OVERFLOW	2
#define HCLGE_ETHERTYPE_KEY_CONFLICT		3

	int return_status;

	if (cmdq_resp) {
		dev_err(&hdev->pdev->dev,
			"cmdq execute failed for get_mac_ethertype_cmd_status, status=%d.\n",
			cmdq_resp);
		return -EIO;
	}

	switch (resp_code) {
	case HCLGE_ETHERTYPE_SUCCESS_ADD:
	case HCLGE_ETHERTYPE_ALREADY_ADD:
		return_status = 0;
		break;
	case HCLGE_ETHERTYPE_MGR_TBL_OVERFLOW:
		dev_err(&hdev->pdev->dev,
			"add mac ethertype failed for manager table overflow.\n");
		return_status = -EIO;
		break;
	case HCLGE_ETHERTYPE_KEY_CONFLICT:
		dev_err(&hdev->pdev->dev,
			"add mac ethertype failed for key conflict.\n");
		return_status = -EIO;
		break;
	default:
		dev_err(&hdev->pdev->dev,
			"add mac ethertype failed for undefined, code=%d.\n",
			resp_code);
		return_status = -EIO;
	}

	return return_status;
}

static int hclge_add_mgr_tbl(struct hclge_dev *hdev,
			     const struct hclge_mac_mgr_tbl_entry_cmd *req)
{
	struct hclge_desc desc;
	u8 resp_code;
	u16 retval;
	int ret;

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_ETHTYPE_ADD, false);
	memcpy(desc.data, req, sizeof(struct hclge_mac_mgr_tbl_entry_cmd));

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"add mac ethertype failed for cmd_send, ret =%d.\n",
			ret);
		return ret;
	}

	resp_code = (le32_to_cpu(desc.data[0]) >> 8) & 0xff;
	retval = le16_to_cpu(desc.retval);

	return hclge_get_mac_ethertype_cmd_status(hdev, retval, resp_code);
}

static int init_mgr_tbl(struct hclge_dev *hdev)
{
	int ret;
	int i;

	for (i = 0; i < ARRAY_SIZE(hclge_mgr_table); i++) {
		ret = hclge_add_mgr_tbl(hdev, &hclge_mgr_table[i]);
		if (ret) {
			dev_err(&hdev->pdev->dev,
				"add mac ethertype failed, ret =%d.\n",
				ret);
			return ret;
		}
	}

	return 0;
}

static void hclge_get_mac_addr(struct hnae3_handle *handle, u8 *p)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
@@ -5271,6 +5406,12 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
		return ret;
	}

	ret = init_mgr_tbl(hdev);
	if (ret) {
		dev_err(&pdev->dev, "manager table init fail, ret =%d\n", ret);
		return ret;
	}

	hclge_dcb_ops_set(hdev);

	timer_setup(&hdev->service_timer, hclge_service_timer, 0);
@@ -5544,6 +5685,318 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
	return ret;
}

static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit,
			      u32 *regs_num_64_bit)
{
	struct hclge_desc desc;
	u32 total_num;
	int ret;

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true);
	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Query register number cmd failed, ret = %d.\n", ret);
		return ret;
	}

	*regs_num_32_bit = le32_to_cpu(desc.data[0]);
	*regs_num_64_bit = le32_to_cpu(desc.data[1]);

	total_num = *regs_num_32_bit + *regs_num_64_bit;
	if (!total_num)
		return -EINVAL;

	return 0;
}

static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num,
				 void *data)
{
#define HCLGE_32_BIT_REG_RTN_DATANUM 8

	struct hclge_desc *desc;
	u32 *reg_val = data;
	__le32 *desc_data;
	int cmd_num;
	int i, k, n;
	int ret;

	if (regs_num == 0)
		return 0;

	cmd_num = DIV_ROUND_UP(regs_num + 2, HCLGE_32_BIT_REG_RTN_DATANUM);
	desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
	if (!desc)
		return -ENOMEM;

	hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true);
	ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Query 32 bit register cmd failed, ret = %d.\n", ret);
		kfree(desc);
		return ret;
	}

	for (i = 0; i < cmd_num; i++) {
		if (i == 0) {
			desc_data = (__le32 *)(&desc[i].data[0]);
			n = HCLGE_32_BIT_REG_RTN_DATANUM - 2;
		} else {
			desc_data = (__le32 *)(&desc[i]);
			n = HCLGE_32_BIT_REG_RTN_DATANUM;
		}
		for (k = 0; k < n; k++) {
			*reg_val++ = le32_to_cpu(*desc_data++);

			regs_num--;
			if (!regs_num)
				break;
		}
	}

	kfree(desc);
	return 0;
}

static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
				 void *data)
{
#define HCLGE_64_BIT_REG_RTN_DATANUM 4

	struct hclge_desc *desc;
	u64 *reg_val = data;
	__le64 *desc_data;
	int cmd_num;
	int i, k, n;
	int ret;

	if (regs_num == 0)
		return 0;

	cmd_num = DIV_ROUND_UP(regs_num + 1, HCLGE_64_BIT_REG_RTN_DATANUM);
	desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
	if (!desc)
		return -ENOMEM;

	hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true);
	ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Query 64 bit register cmd failed, ret = %d.\n", ret);
		kfree(desc);
		return ret;
	}

	for (i = 0; i < cmd_num; i++) {
		if (i == 0) {
			desc_data = (__le64 *)(&desc[i].data[0]);
			n = HCLGE_64_BIT_REG_RTN_DATANUM - 1;
		} else {
			desc_data = (__le64 *)(&desc[i]);
			n = HCLGE_64_BIT_REG_RTN_DATANUM;
		}
		for (k = 0; k < n; k++) {
			*reg_val++ = le64_to_cpu(*desc_data++);

			regs_num--;
			if (!regs_num)
				break;
		}
	}

	kfree(desc);
	return 0;
}

static int hclge_get_regs_len(struct hnae3_handle *handle)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	u32 regs_num_32_bit, regs_num_64_bit;
	int ret;

	ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Get register number failed, ret = %d.\n", ret);
		return -EOPNOTSUPP;
	}

	return regs_num_32_bit * sizeof(u32) + regs_num_64_bit * sizeof(u64);
}

static void hclge_get_regs(struct hnae3_handle *handle, u32 *version,
			   void *data)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	u32 regs_num_32_bit, regs_num_64_bit;
	int ret;

	*version = hdev->fw_version;

	ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Get register number failed, ret = %d.\n", ret);
		return;
	}

	ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, data);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Get 32 bit register failed, ret = %d.\n", ret);
		return;
	}

	data = (u32 *)data + regs_num_32_bit;
	ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit,
				    data);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"Get 64 bit register failed, ret = %d.\n", ret);
}

static int hclge_set_led_status_sfp(struct hclge_dev *hdev, u8 speed_led_status,
				    u8 act_led_status, u8 link_led_status,
				    u8 locate_led_status)
{
	struct hclge_set_led_state_cmd *req;
	struct hclge_desc desc;
	int ret;

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_LED_STATUS_CFG, false);

	req = (struct hclge_set_led_state_cmd *)desc.data;
	hnae_set_field(req->port_speed_led_config, HCLGE_LED_PORT_SPEED_STATE_M,
		       HCLGE_LED_PORT_SPEED_STATE_S, speed_led_status);
	hnae_set_field(req->link_led_config, HCLGE_LED_ACTIVITY_STATE_M,
		       HCLGE_LED_ACTIVITY_STATE_S, act_led_status);
	hnae_set_field(req->activity_led_config, HCLGE_LED_LINK_STATE_M,
		       HCLGE_LED_LINK_STATE_S, link_led_status);
	hnae_set_field(req->locate_led_config, HCLGE_LED_LOCATE_STATE_M,
		       HCLGE_LED_LOCATE_STATE_S, locate_led_status);

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"Send set led state cmd error, ret =%d\n", ret);

	return ret;
}

enum hclge_led_status {
	HCLGE_LED_OFF,
	HCLGE_LED_ON,
	HCLGE_LED_NO_CHANGE = 0xFF,
};

static int hclge_set_led_id(struct hnae3_handle *handle,
			    enum ethtool_phys_id_state status)
{
#define BLINK_FREQUENCY		2
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	struct phy_device *phydev = hdev->hw.mac.phydev;
	int ret = 0;

	if (phydev || hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_FIBER)
		return -EOPNOTSUPP;

	switch (status) {
	case ETHTOOL_ID_ACTIVE:
		ret = hclge_set_led_status_sfp(hdev,
					       HCLGE_LED_NO_CHANGE,
					       HCLGE_LED_NO_CHANGE,
					       HCLGE_LED_NO_CHANGE,
					       HCLGE_LED_ON);
		break;
	case ETHTOOL_ID_INACTIVE:
		ret = hclge_set_led_status_sfp(hdev,
					       HCLGE_LED_NO_CHANGE,
					       HCLGE_LED_NO_CHANGE,
					       HCLGE_LED_NO_CHANGE,
					       HCLGE_LED_OFF);
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

enum hclge_led_port_speed {
	HCLGE_SPEED_LED_FOR_1G,
	HCLGE_SPEED_LED_FOR_10G,
	HCLGE_SPEED_LED_FOR_25G,
	HCLGE_SPEED_LED_FOR_40G,
	HCLGE_SPEED_LED_FOR_50G,
	HCLGE_SPEED_LED_FOR_100G,
};

static u8 hclge_led_get_speed_status(u32 speed)
{
	u8 speed_led;

	switch (speed) {
	case HCLGE_MAC_SPEED_1G:
		speed_led = HCLGE_SPEED_LED_FOR_1G;
		break;
	case HCLGE_MAC_SPEED_10G:
		speed_led = HCLGE_SPEED_LED_FOR_10G;
		break;
	case HCLGE_MAC_SPEED_25G:
		speed_led = HCLGE_SPEED_LED_FOR_25G;
		break;
	case HCLGE_MAC_SPEED_40G:
		speed_led = HCLGE_SPEED_LED_FOR_40G;
		break;
	case HCLGE_MAC_SPEED_50G:
		speed_led = HCLGE_SPEED_LED_FOR_50G;
		break;
	case HCLGE_MAC_SPEED_100G:
		speed_led = HCLGE_SPEED_LED_FOR_100G;
		break;
	default:
		speed_led = HCLGE_LED_NO_CHANGE;
	}

	return speed_led;
}

static int hclge_update_led_status(struct hclge_dev *hdev)
{
	u8 port_speed_status, link_status, activity_status;
	u64 rx_pkts, tx_pkts;

	if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_FIBER)
		return 0;

	port_speed_status = hclge_led_get_speed_status(hdev->hw.mac.speed);

	rx_pkts = hdev->hw_stats.mac_stats.mac_rx_total_pkt_num;
	tx_pkts = hdev->hw_stats.mac_stats.mac_tx_total_pkt_num;
	if (rx_pkts != hdev->rx_pkts_for_led ||
	    tx_pkts != hdev->tx_pkts_for_led)
		activity_status = HCLGE_LED_ON;
	else
		activity_status = HCLGE_LED_OFF;
	hdev->rx_pkts_for_led = rx_pkts;
	hdev->tx_pkts_for_led = tx_pkts;

	if (hdev->hw.mac.link)
		link_status = HCLGE_LED_ON;
	else
		link_status = HCLGE_LED_OFF;

	return hclge_set_led_status_sfp(hdev, port_speed_status,
					activity_status, link_status,
					HCLGE_LED_NO_CHANGE);
}

static const struct hnae3_ae_ops hclge_ops = {
	.init_ae_dev = hclge_init_ae_dev,
	.uninit_ae_dev = hclge_uninit_ae_dev,
@@ -5595,6 +6048,9 @@ static const struct hnae3_ae_ops hclge_ops = {
	.set_channels = hclge_set_channels,
	.get_channels = hclge_get_channels,
	.get_flowctrl_adv = hclge_get_flowctrl_adv,
	.get_regs_len = hclge_get_regs_len,
	.get_regs = hclge_get_regs,
	.set_led_id = hclge_set_led_id,
};

static struct hnae3_ae_algo ae_algo = {
+3 −0
Original line number Diff line number Diff line
@@ -550,6 +550,9 @@ struct hclge_dev {
	bool accept_mta_mc; /* Whether accept mta filter multicast */

	struct hclge_vlan_type_cfg vlan_type_cfg;

	u64 rx_pkts_for_led;
	u64 tx_pkts_for_led;
};

/* VPort level vlan tag configuration for TX direction */