Commit f96c7722 authored by Jian Shen's avatar Jian Shen Committed by Zheng Zengkai
Browse files

net: hns3: refine the handling for VF heartbeat

driver inclusion
category:feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I62HX2



----------------------------------------------------------------------

Currently, the PF check the VF alive by the KEEP_ALVE
mailbox from VF. VF keep sending the mailbox per 2
seconds. Once PF lost the mailbox for more than 8
seconds, it will regards the VF is abnormal, and stop
notifying the state change to VF, include link state,
vf mac, reset, even though it receives the KEEP_ALIVE
mailbox again. It's inreasonable.

This patch fixes it. PF will record the state change which
need to notify VF when lost the VF's KEEP_ALIVE mailbox.
And notify VF when receive the mailbox again. Introduce a
new flag HCLGE_VPORT_STATE_INITED, used to distinguish the
case whether VF driver loaded or not. For VF will query
these states when initializing, so it's unnecessary to
notify it in this case.

Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarJiantao Xiao <xiaojiantao1@h-partners.com>
Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Reviewed-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 4142005a
Loading
Loading
Loading
Loading
+37 −14
Original line number Diff line number Diff line
@@ -3816,9 +3816,17 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
			return ret;
		}

		if (!reset || !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
		if (!reset ||
		    !test_bit(HCLGE_VPORT_STATE_INITED, &vport->state))
			continue;

		if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state) &&
		    hdev->reset_type == HNAE3_FUNC_RESET) {
			set_bit(HCLGE_VPORT_NEED_NOTIFY_RESET,
				&vport->need_notify);
			continue;
		}

		/* Inform VF to process the reset.
		 * hclge_inform_reset_assert_to_vf may fail if VF
		 * driver is not loaded.
@@ -4541,12 +4549,15 @@ static void hclge_update_vport_alive(struct hclge_dev *hdev)
	for (i = 1; i < hdev->num_alloc_vport; i++) {
		struct hclge_vport *vport = &hdev->vport[i];

		if (time_after(jiffies, vport->last_active_jiffies + 8 * HZ))
		if (!test_bit(HCLGE_VPORT_STATE_INITED, &vport->state) ||
		    !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
			continue;
		if (time_after(jiffies, vport->last_active_jiffies + 8 * HZ)) {
			clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);

		/* If vf is not alive, set to default value */
		if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
			vport->mps = HCLGE_MAC_DEFAULT_FRAME;
			dev_warn(&hdev->pdev->dev,
				 "vf %u heartbeat timeout\n",
				 i - HCLGE_VF_VPORT_START_NUM);
		}
	}
}

@@ -8256,9 +8267,11 @@ int hclge_vport_start(struct hclge_vport *vport)
{
	struct hclge_dev *hdev = vport->back;

	set_bit(HCLGE_VPORT_STATE_INITED, &vport->state);
	set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
	set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state);
	vport->last_active_jiffies = jiffies;
	vport->need_notify = 0;

	if (test_bit(vport->vport_id, hdev->vport_config_block)) {
		if (vport->vport_id) {
@@ -8276,7 +8289,9 @@ int hclge_vport_start(struct hclge_vport *vport)

void hclge_vport_stop(struct hclge_vport *vport)
{
	clear_bit(HCLGE_VPORT_STATE_INITED, &vport->state);
	clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
	vport->need_notify = 0;
}

static int hclge_client_start(struct hnae3_handle *handle)
@@ -9429,7 +9444,8 @@ static int hclge_set_vf_mac(struct hnae3_handle *handle, int vf,
		return 0;
	}

	dev_info(&hdev->pdev->dev, "MAC of VF %d has been set to %s\n",
	dev_info(&hdev->pdev->dev,
		 "MAC of VF %d has been set to %s, will be active after vf reset\n",
		 vf, format_mac_addr);
	return 0;
}
@@ -10692,12 +10708,16 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
	 * for DEVICE_VERSION_V3, vf doesn't need to know about the port based
	 * VLAN state.
	 */
	if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 &&
	    test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
	if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) {
		if (test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
			(void)hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
								vport->vport_id,
							state, &vlan_info);

								state,
								&vlan_info);
		else
			set_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN,
				&vport->need_notify);
	}
	return 0;
}

@@ -12237,7 +12257,7 @@ static void hclge_reset_vport_state(struct hclge_dev *hdev)
	int i;

	for (i = 0; i < hdev->num_alloc_vport; i++) {
		hclge_vport_stop(vport);
		clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
		vport++;
	}
}
@@ -13240,6 +13260,9 @@ static void hclge_clear_vport_vf_info(struct hclge_vport *vport, int vfid)
	struct hclge_vlan_info vlan_info;
	int ret;

	hclge_vport_stop(vport);
	vport->mps = 0;

	/* after disable sriov, clean VF rate configured by PF */
	ret = hclge_tm_qs_shaper_cfg(vport, 0);
	if (ret)
+7 −0
Original line number Diff line number Diff line
@@ -977,9 +977,15 @@ enum HCLGE_VPORT_STATE {
	HCLGE_VPORT_STATE_MAC_TBL_CHANGE,
	HCLGE_VPORT_STATE_PROMISC_CHANGE,
	HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE,
	HCLGE_VPORT_STATE_INITED,
	HCLGE_VPORT_STATE_MAX
};

enum HCLGE_VPORT_NEED_NOTIFY {
	HCLGE_VPORT_NEED_NOTIFY_RESET,
	HCLGE_VPORT_NEED_NOTIFY_VF_VLAN,
};

struct hclge_vlan_info {
	u16 vlan_proto; /* so far support 802.1Q only */
	u16 qos;
@@ -1027,6 +1033,7 @@ struct hclge_vport {
	struct hnae3_handle roh;

	unsigned long state;
	unsigned long need_notify;
	unsigned long last_active_jiffies;
	u32 mps; /* Max packet size */
	struct hclge_vf_info vf_info;
+62 −9
Original line number Diff line number Diff line
@@ -124,17 +124,26 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
	return status;
}

static int hclge_inform_vf_reset(struct hclge_vport *vport, u16 reset_type)
{
	__le16 msg_data;
	u8 dest_vfid;

	dest_vfid = (u8)vport->vport_id;
	msg_data = cpu_to_le16(reset_type);

	/* send this requested info to VF */
	return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data),
				  HCLGE_MBX_ASSERTING_RESET, dest_vfid);
}

int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
{
	struct hclge_dev *hdev = vport->back;
	__le16 msg_data;
	u16 reset_type;
	u8 dest_vfid;

	BUILD_BUG_ON(HNAE3_MAX_RESET > U16_MAX);

	dest_vfid = (u8)vport->vport_id;

	if (hdev->reset_type == HNAE3_FUNC_RESET)
		reset_type = HNAE3_VF_PF_FUNC_RESET;
	else if (hdev->reset_type == HNAE3_FLR_RESET)
@@ -142,11 +151,7 @@ int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
	else
		reset_type = HNAE3_VF_FUNC_RESET;

	msg_data = cpu_to_le16(reset_type);

	/* send this requested info to VF */
	return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data),
				  HCLGE_MBX_ASSERTING_RESET, dest_vfid);
	return hclge_inform_vf_reset(vport, reset_type);
}

static void hclge_free_vector_ring_chain(struct hnae3_ring_chain_node *head)
@@ -652,9 +657,56 @@ static int hclge_reset_vf(struct hclge_vport *vport)
	return hclge_func_reset_cmd(hdev, vport->vport_id);
}

static void hclge_notify_vf_config(struct hclge_vport *vport)
{
	struct hclge_dev *hdev = vport->back;
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
	struct hclge_port_base_vlan_config *vlan_cfg;
	int ret;

	hclge_push_vf_link_status(vport);
	if (test_bit(HCLGE_VPORT_NEED_NOTIFY_RESET, &vport->need_notify)) {
		ret = hclge_inform_vf_reset(vport, HNAE3_VF_PF_FUNC_RESET);
		if (ret) {
			dev_err(&hdev->pdev->dev,
				"failed to inform VF %u reset!",
				vport->vport_id - HCLGE_VF_VPORT_START_NUM);
			return;
		}
		vport->need_notify = 0;
		return;
	}

	if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 &&
	    test_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, &vport->need_notify)) {
		vlan_cfg = &vport->port_base_vlan_cfg;
		ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
							vport->vport_id,
							vlan_cfg->state,
							&vlan_cfg->vlan_info);
		if (ret) {
			dev_err(&hdev->pdev->dev,
				"failed to inform VF %u port base vlan!",
				vport->vport_id - HCLGE_VF_VPORT_START_NUM);
			return;
		}
		clear_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, &vport->need_notify);
	}
}

static void hclge_vf_keep_alive(struct hclge_vport *vport)
{
	struct hclge_dev *hdev = vport->back;

	vport->last_active_jiffies = jiffies;

	if (test_bit(HCLGE_VPORT_STATE_INITED, &vport->state) &&
	    !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
		set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
		dev_info(&hdev->pdev->dev, "VF %u is alive!",
			 vport->vport_id - HCLGE_VF_VPORT_START_NUM);
		hclge_notify_vf_config(vport);
	}
}

static int hclge_set_vf_mtu(struct hclge_vport *vport,
@@ -954,6 +1006,7 @@ static int hclge_mbx_vf_uninit_handler(struct hclge_mbx_ops_param *param)
	hclge_rm_vport_all_mac_table(param->vport, true,
				     HCLGE_MAC_ADDR_MC);
	hclge_rm_vport_all_vlan_table(param->vport, true);
	param->vport->mps = 0;
	return 0;
}