Skip to content

Commit 21e043c

Browse files
IronShendavem330
authored andcommitted
net: hns3: fix set port based VLAN for PF
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. Indeed, ndo_set_vf_vlan() is expected to enable or disable port based VLAN (hardware inserts a specified VLAN tag to all TX packets for a specified VF) . When enable port based VLAN, we use port based VLAN id as VLAN filter entry. When disable port based VLAN, we use VLAN id of VLAN device. This patch fixes it for PF, enable/disable port based VLAN when calls ndo_set_vf_vlan(). Fixes: 46a3df9 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support") Signed-off-by: Jian Shen <[email protected]> Signed-off-by: Huazhong Tan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 44e626f commit 21e043c

File tree

3 files changed

+203
-34
lines changed

3 files changed

+203
-34
lines changed

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

Lines changed: 201 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6585,30 +6585,6 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
65856585
return ret;
65866586
}
65876587

6588-
int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
6589-
u16 vlan_id, bool is_kill)
6590-
{
6591-
struct hclge_vport *vport = hclge_get_vport(handle);
6592-
struct hclge_dev *hdev = vport->back;
6593-
6594-
return hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id, vlan_id,
6595-
0, is_kill);
6596-
}
6597-
6598-
static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
6599-
u16 vlan, u8 qos, __be16 proto)
6600-
{
6601-
struct hclge_vport *vport = hclge_get_vport(handle);
6602-
struct hclge_dev *hdev = vport->back;
6603-
6604-
if ((vfid >= hdev->num_alloc_vfs) || (vlan > 4095) || (qos > 7))
6605-
return -EINVAL;
6606-
if (proto != htons(ETH_P_8021Q))
6607-
return -EPROTONOSUPPORT;
6608-
6609-
return hclge_set_vlan_filter_hw(hdev, proto, vfid, vlan, qos, false);
6610-
}
6611-
66126588
static int hclge_set_vlan_tx_offload_cfg(struct hclge_vport *vport)
66136589
{
66146590
struct hclge_tx_vtag_cfg *vcfg = &vport->txvlan_cfg;
@@ -6833,7 +6809,8 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
68336809
return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
68346810
}
68356811

6836-
void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id)
6812+
static void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
6813+
bool writen_to_tbl)
68376814
{
68386815
struct hclge_vport_vlan_cfg *vlan;
68396816

@@ -6845,14 +6822,38 @@ void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id)
68456822
if (!vlan)
68466823
return;
68476824

6848-
vlan->hd_tbl_status = true;
6825+
vlan->hd_tbl_status = writen_to_tbl;
68496826
vlan->vlan_id = vlan_id;
68506827

68516828
list_add_tail(&vlan->node, &vport->vlan_list);
68526829
}
68536830

6854-
void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
6855-
bool is_write_tbl)
6831+
static int hclge_add_vport_all_vlan_table(struct hclge_vport *vport)
6832+
{
6833+
struct hclge_vport_vlan_cfg *vlan, *tmp;
6834+
struct hclge_dev *hdev = vport->back;
6835+
int ret;
6836+
6837+
list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
6838+
if (!vlan->hd_tbl_status) {
6839+
ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
6840+
vport->vport_id,
6841+
vlan->vlan_id, 0, false);
6842+
if (ret) {
6843+
dev_err(&hdev->pdev->dev,
6844+
"restore vport vlan list failed, ret=%d\n",
6845+
ret);
6846+
return ret;
6847+
}
6848+
}
6849+
vlan->hd_tbl_status = true;
6850+
}
6851+
6852+
return 0;
6853+
}
6854+
6855+
static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
6856+
bool is_write_tbl)
68566857
{
68576858
struct hclge_vport_vlan_cfg *vlan, *tmp;
68586859
struct hclge_dev *hdev = vport->back;
@@ -6929,6 +6930,178 @@ int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
69296930
return hclge_set_vlan_rx_offload_cfg(vport);
69306931
}
69316932

6933+
static int hclge_update_vlan_filter_entries(struct hclge_vport *vport,
6934+
u16 port_base_vlan_state,
6935+
struct hclge_vlan_info *new_info,
6936+
struct hclge_vlan_info *old_info)
6937+
{
6938+
struct hclge_dev *hdev = vport->back;
6939+
int ret;
6940+
6941+
if (port_base_vlan_state == HNAE3_PORT_BASE_VLAN_ENABLE) {
6942+
hclge_rm_vport_all_vlan_table(vport, false);
6943+
return hclge_set_vlan_filter_hw(hdev,
6944+
htons(new_info->vlan_proto),
6945+
vport->vport_id,
6946+
new_info->vlan_tag,
6947+
new_info->qos, false);
6948+
}
6949+
6950+
ret = hclge_set_vlan_filter_hw(hdev, htons(old_info->vlan_proto),
6951+
vport->vport_id, old_info->vlan_tag,
6952+
old_info->qos, true);
6953+
if (ret)
6954+
return ret;
6955+
6956+
return hclge_add_vport_all_vlan_table(vport);
6957+
}
6958+
6959+
int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
6960+
struct hclge_vlan_info *vlan_info)
6961+
{
6962+
struct hnae3_handle *nic = &vport->nic;
6963+
struct hclge_vlan_info *old_vlan_info;
6964+
struct hclge_dev *hdev = vport->back;
6965+
int ret;
6966+
6967+
old_vlan_info = &vport->port_base_vlan_cfg.vlan_info;
6968+
6969+
ret = hclge_vlan_offload_cfg(vport, state, vlan_info->vlan_tag);
6970+
if (ret)
6971+
return ret;
6972+
6973+
if (state == HNAE3_PORT_BASE_VLAN_MODIFY) {
6974+
/* add new VLAN tag */
6975+
ret = hclge_set_vlan_filter_hw(hdev, vlan_info->vlan_proto,
6976+
vport->vport_id,
6977+
vlan_info->vlan_tag,
6978+
vlan_info->qos, false);
6979+
if (ret)
6980+
return ret;
6981+
6982+
/* remove old VLAN tag */
6983+
ret = hclge_set_vlan_filter_hw(hdev, old_vlan_info->vlan_proto,
6984+
vport->vport_id,
6985+
old_vlan_info->vlan_tag,
6986+
old_vlan_info->qos, true);
6987+
if (ret)
6988+
return ret;
6989+
6990+
goto update;
6991+
}
6992+
6993+
ret = hclge_update_vlan_filter_entries(vport, state, vlan_info,
6994+
old_vlan_info);
6995+
if (ret)
6996+
return ret;
6997+
6998+
/* update state only when disable/enable port based VLAN */
6999+
vport->port_base_vlan_cfg.state = state;
7000+
if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
7001+
nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_DISABLE;
7002+
else
7003+
nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
7004+
7005+
update:
7006+
vport->port_base_vlan_cfg.vlan_info.vlan_tag = vlan_info->vlan_tag;
7007+
vport->port_base_vlan_cfg.vlan_info.qos = vlan_info->qos;
7008+
vport->port_base_vlan_cfg.vlan_info.vlan_proto = vlan_info->vlan_proto;
7009+
7010+
return 0;
7011+
}
7012+
7013+
static u16 hclge_get_port_base_vlan_state(struct hclge_vport *vport,
7014+
enum hnae3_port_base_vlan_state state,
7015+
u16 vlan)
7016+
{
7017+
if (state == HNAE3_PORT_BASE_VLAN_DISABLE) {
7018+
if (!vlan)
7019+
return HNAE3_PORT_BASE_VLAN_NOCHANGE;
7020+
else
7021+
return HNAE3_PORT_BASE_VLAN_ENABLE;
7022+
} else {
7023+
if (!vlan)
7024+
return HNAE3_PORT_BASE_VLAN_DISABLE;
7025+
else if (vport->port_base_vlan_cfg.vlan_info.vlan_tag == vlan)
7026+
return HNAE3_PORT_BASE_VLAN_NOCHANGE;
7027+
else
7028+
return HNAE3_PORT_BASE_VLAN_MODIFY;
7029+
}
7030+
}
7031+
7032+
static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
7033+
u16 vlan, u8 qos, __be16 proto)
7034+
{
7035+
struct hclge_vport *vport = hclge_get_vport(handle);
7036+
struct hclge_dev *hdev = vport->back;
7037+
struct hclge_vlan_info vlan_info;
7038+
u16 state;
7039+
int ret;
7040+
7041+
if (hdev->pdev->revision == 0x20)
7042+
return -EOPNOTSUPP;
7043+
7044+
/* qos is a 3 bits value, so can not be bigger than 7 */
7045+
if (vfid >= hdev->num_alloc_vfs || vlan > VLAN_N_VID - 1 || qos > 7)
7046+
return -EINVAL;
7047+
if (proto != htons(ETH_P_8021Q))
7048+
return -EPROTONOSUPPORT;
7049+
7050+
vport = &hdev->vport[vfid];
7051+
state = hclge_get_port_base_vlan_state(vport,
7052+
vport->port_base_vlan_cfg.state,
7053+
vlan);
7054+
if (state == HNAE3_PORT_BASE_VLAN_NOCHANGE)
7055+
return 0;
7056+
7057+
vlan_info.vlan_tag = vlan;
7058+
vlan_info.qos = qos;
7059+
vlan_info.vlan_proto = ntohs(proto);
7060+
7061+
/* update port based VLAN for PF */
7062+
if (!vfid) {
7063+
hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
7064+
ret = hclge_update_port_base_vlan_cfg(vport, state, &vlan_info);
7065+
hclge_notify_client(hdev, HNAE3_UP_CLIENT);
7066+
7067+
return ret;
7068+
}
7069+
7070+
return -EOPNOTSUPP;
7071+
}
7072+
7073+
int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
7074+
u16 vlan_id, bool is_kill)
7075+
{
7076+
struct hclge_vport *vport = hclge_get_vport(handle);
7077+
struct hclge_dev *hdev = vport->back;
7078+
bool writen_to_tbl = false;
7079+
int ret = 0;
7080+
7081+
/* when port based VLAN enabled, we use port based VLAN as the VLAN
7082+
* filter entry. In this case, we don't update VLAN filter table
7083+
* when user add new VLAN or remove exist VLAN, just update the vport
7084+
* VLAN list. The VLAN id in VLAN list won't be writen in VLAN filter
7085+
* table until port based VLAN disabled
7086+
*/
7087+
if (handle->port_base_vlan_state == HNAE3_PORT_BASE_VLAN_DISABLE) {
7088+
ret = hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id,
7089+
vlan_id, 0, is_kill);
7090+
writen_to_tbl = true;
7091+
}
7092+
7093+
if (ret)
7094+
return ret;
7095+
7096+
if (is_kill)
7097+
hclge_rm_vport_vlan_table(vport, vlan_id, false);
7098+
else
7099+
hclge_add_vport_vlan_table(vport, vlan_id,
7100+
writen_to_tbl);
7101+
7102+
return 0;
7103+
}
7104+
69327105
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps)
69337106
{
69347107
struct hclge_config_max_frm_size_cmd *req;

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,9 +937,8 @@ void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
937937
void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
938938
enum HCLGE_MAC_ADDR_TYPE mac_type);
939939
void hclge_uninit_vport_mac_table(struct hclge_dev *hdev);
940-
void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id);
941-
void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
942-
bool is_write_tbl);
943940
void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list);
944941
void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev);
942+
int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
943+
struct hclge_vlan_info *vlan_info);
945944
#endif

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,6 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
305305
memcpy(&proto, &mbx_req->msg[5], sizeof(proto));
306306
status = hclge_set_vlan_filter(handle, cpu_to_be16(proto),
307307
vlan, is_kill);
308-
if (!status)
309-
is_kill ? hclge_rm_vport_vlan_table(vport, vlan, false)
310-
: hclge_add_vport_vlan_table(vport, vlan);
311308
} else if (mbx_req->msg[1] == HCLGE_MBX_VLAN_RX_OFF_CFG) {
312309
struct hnae3_handle *handle = &vport->nic;
313310
bool en = mbx_req->msg[2] ? true : false;

0 commit comments

Comments
 (0)