Commit 92f11ea1 authored by Jian Shen's avatar Jian Shen Committed by David S. Miller
Browse files

net: hns3: fix set port based VLAN issue for VF



In original codes, ndo_set_vf_vlan() in hns3 driver was implemented
wrong. It adds or removes VLAN into VLAN filter for VF, but VF is
unaware of it.

This patch fixes it. When VF loads up, it firstly queries the port
based VLAN state from PF. When user change port based VLAN state
from PF, PF firstly checks whether the VF is alive. If the VF is
alive, then PF notifies the VF the modification; otherwise PF
configure the port based VLAN state directly.

Fixes: 46a3df9f ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support")
Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 21e043cd
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ enum HCLGE_MBX_OPCODE {
	HCLGE_MBX_GET_QID_IN_PF,	/* (VF -> PF) get queue id in pf */
	HCLGE_MBX_LINK_STAT_MODE,	/* (PF -> VF) link mode has changed */
	HCLGE_MBX_GET_LINK_MODE,	/* (VF -> PF) get the link mode of pf */
	HLCGE_MBX_PUSH_VLAN_INFO,	/* (PF -> VF) push port base vlan */
	HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */

	HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
@@ -63,6 +64,8 @@ enum hclge_mbx_vlan_cfg_subcode {
	HCLGE_MBX_VLAN_FILTER = 0,	/* set vlan filter */
	HCLGE_MBX_VLAN_TX_OFF_CFG,	/* set tx side vlan offload */
	HCLGE_MBX_VLAN_RX_OFF_CFG,	/* set rx side vlan offload */
	HCLGE_MBX_PORT_BASE_VLAN_CFG,	/* set port based vlan configuration */
	HCLGE_MBX_GET_PORT_BASE_VLAN_STATE,	/* get port based vlan state */
};

#define HCLGE_MBX_MAX_MSG_SIZE	16
+10 −1
Original line number Diff line number Diff line
@@ -7067,7 +7067,16 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
		return ret;
	}

	return -EOPNOTSUPP;
	if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
		return hclge_update_port_base_vlan_cfg(vport, state,
						       &vlan_info);
	} else {
		ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
							(u8)vfid, state,
							vlan, qos,
							ntohs(proto));
		return ret;
	}
}

int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
+3 −0
Original line number Diff line number Diff line
@@ -941,4 +941,7 @@ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list);
void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev);
int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
				    struct hclge_vlan_info *vlan_info);
int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
				      u16 state, u16 vlan_tag, u16 qos,
				      u16 vlan_proto);
#endif
+33 −6
Original line number Diff line number Diff line
@@ -289,9 +289,25 @@ static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport,
	return 0;
}

int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
				      u16 state, u16 vlan_tag, u16 qos,
				      u16 vlan_proto)
{
#define MSG_DATA_SIZE	8

	u8 msg_data[MSG_DATA_SIZE];

	memcpy(&msg_data[0], &state, sizeof(u16));
	memcpy(&msg_data[2], &vlan_proto, sizeof(u16));
	memcpy(&msg_data[4], &qos, sizeof(u16));
	memcpy(&msg_data[6], &vlan_tag, sizeof(u16));

	return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
				  HLCGE_MBX_PUSH_VLAN_INFO, vfid);
}

static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
				 struct hclge_mbx_vf_to_pf_cmd *mbx_req,
				 bool gen_resp)
				 struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{
	int status = 0;

@@ -310,11 +326,22 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
		bool en = mbx_req->msg[2] ? true : false;

		status = hclge_en_hw_strip_rxvtag(handle, en);
	} else if (mbx_req->msg[1] == HCLGE_MBX_PORT_BASE_VLAN_CFG) {
		struct hclge_vlan_info *vlan_info;
		u16 *state;

		state = (u16 *)&mbx_req->msg[2];
		vlan_info = (struct hclge_vlan_info *)&mbx_req->msg[4];
		status = hclge_update_port_base_vlan_cfg(vport, *state,
							 vlan_info);
	} else if (mbx_req->msg[1] == HCLGE_MBX_GET_PORT_BASE_VLAN_STATE) {
		u8 state;

		state = vport->port_base_vlan_cfg.state;
		status = hclge_gen_resp_to_vf(vport, mbx_req, 0, &state,
					      sizeof(u8));
	}

	if (gen_resp)
		status = hclge_gen_resp_to_vf(vport, mbx_req, status, NULL, 0);

	return status;
}

@@ -584,7 +611,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
					ret);
			break;
		case HCLGE_MBX_SET_VLAN:
			ret = hclge_set_vf_vlan_cfg(vport, req, false);
			ret = hclge_set_vf_vlan_cfg(vport, req);
			if (ret)
				dev_err(&hdev->pdev->dev,
					"PF failed(%d) to config VF's VLAN\n",
+51 −0
Original line number Diff line number Diff line
@@ -245,6 +245,27 @@ static int hclgevf_get_tc_info(struct hclgevf_dev *hdev)
	return 0;
}

static int hclgevf_get_port_base_vlan_filter_state(struct hclgevf_dev *hdev)
{
	struct hnae3_handle *nic = &hdev->nic;
	u8 resp_msg;
	int ret;

	ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
				   HCLGE_MBX_GET_PORT_BASE_VLAN_STATE,
				   NULL, 0, true, &resp_msg, sizeof(u8));
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"VF request to get port based vlan state failed %d",
			ret);
		return ret;
	}

	nic->port_base_vlan_state = resp_msg;

	return 0;
}

static int hclgevf_get_queue_info(struct hclgevf_dev *hdev)
{
#define HCLGEVF_TQPS_RSS_INFO_LEN	6
@@ -1834,6 +1855,11 @@ static int hclgevf_configure(struct hclgevf_dev *hdev)
{
	int ret;

	/* get current port based vlan state from PF */
	ret = hclgevf_get_port_base_vlan_filter_state(hdev);
	if (ret)
		return ret;

	/* get queue configuration from PF */
	ret = hclgevf_get_queue_info(hdev);
	if (ret)
@@ -2790,6 +2816,31 @@ static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
	}
}

void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
					u8 *port_base_vlan_info, u8 data_size)
{
	struct hnae3_handle *nic = &hdev->nic;

	rtnl_lock();
	hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
	rtnl_unlock();

	/* send msg to PF and wait update port based vlan info */
	hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
			     HCLGE_MBX_PORT_BASE_VLAN_CFG,
			     port_base_vlan_info, data_size,
			     false, NULL, 0);

	if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
		nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_DISABLE;
	else
		nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;

	rtnl_lock();
	hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
	rtnl_unlock();
}

static const struct hnae3_ae_ops hclgevf_ops = {
	.init_ae_dev = hclgevf_init_ae_dev,
	.uninit_ae_dev = hclgevf_uninit_ae_dev,
Loading