Commit 52798618 authored by Jian Shen's avatar Jian Shen Committed by Jiantao Xiao
Browse files

net: hns3: fix VF promisc mode not update when mac table full

mainline inclusion
from mainline-v6.2-rc3
commit 8ee57c7b
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6A42Q
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8ee57c7b8406c7aa8ca31e014440c87c6383f429



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

Currently, it missed set HCLGE_VPORT_STATE_PROMISC_CHANGE
flag for VF when vport->overflow_promisc_flags changed.
So the VF won't check whether to update promisc mode in
this case. So add it.

Fixes: 1e6e7610 ("net: hns3: configure promisc mode for VF asynchronously")
Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarHao Lan <lanhao@huawei.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarJiantao Xiao <xiaojiantao1@h-partners.com>
parent c9d39962
Loading
Loading
Loading
Loading
+43 −32
Original line number Diff line number Diff line
@@ -13487,60 +13487,71 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable)
	return ret;
}

static void hclge_sync_promisc_mode(struct hclge_dev *hdev)
static int hclge_sync_vport_promisc_mode(struct hclge_vport *vport)
{
	struct hclge_vport *vport = &hdev->vport[0];
	struct hnae3_handle *handle = &vport->nic;
	struct hclge_dev *hdev = vport->back;
	bool uc_en = false;
	bool mc_en = false;
	u8 tmp_flags;
	bool bc_en;
	int ret;
	u16 i;

	if (vport->last_promisc_flags != vport->overflow_promisc_flags) {
		set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state);
		vport->last_promisc_flags = vport->overflow_promisc_flags;
	}

	if (test_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state)) {
	if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE,
				&vport->state))
		return 0;

	/* for PF */
	if (!vport->vport_id) {
		tmp_flags = handle->netdev_flags | vport->last_promisc_flags;
		ret = hclge_set_promisc_mode(handle, tmp_flags & HNAE3_UPE,
					     tmp_flags & HNAE3_MPE);
		if (!ret) {
			clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE,
				  &vport->state);
		if (!ret)
			set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE,
				&vport->state);
		}
		else
			set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE,
				&vport->state);
		return ret;
	}

	for (i = 1; i < hdev->num_alloc_vport; i++) {
		bool uc_en = false;
		bool mc_en = false;
		bool bc_en;

		vport = &hdev->vport[i];

		if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE,
					&vport->state))
			continue;

	/* for VF */
	if (vport->vf_info.trusted) {
		uc_en = vport->vf_info.request_uc_en > 0 ||
				vport->overflow_promisc_flags &
				HNAE3_OVERFLOW_UPE;
			vport->overflow_promisc_flags & HNAE3_OVERFLOW_UPE;
		mc_en = vport->vf_info.request_mc_en > 0 ||
				vport->overflow_promisc_flags &
				HNAE3_OVERFLOW_MPE;
			vport->overflow_promisc_flags & HNAE3_OVERFLOW_MPE;
	}
	bc_en = vport->vf_info.request_bc_en > 0;

	ret = hclge_cmd_set_promisc_mode(hdev, vport->vport_id, uc_en,
					 mc_en, bc_en);
	if (ret) {
			set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE,
				&vport->state);
			return;
		set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state);
		return ret;
	}
	hclge_set_vport_vlan_fltr_change(vport);

	return 0;
}

static void hclge_sync_promisc_mode(struct hclge_dev *hdev)
{
	struct hclge_vport *vport;
	int ret;
	u16 i;

	for (i = 0; i < hdev->num_alloc_vport; i++) {
		vport = &hdev->vport[i];

		ret = hclge_sync_vport_promisc_mode(vport);
		if (ret)
			return;
	}
}