You need to sign in or sign up before continuing.
提交 b0493099 编写于 作者: G Guojia Liao 提交者: Yang Yingliang

net: hns3: fix port base vlan add fail when concurrent with reset

driver inclusion
category: bugfix
bugzilla: NA
CVE: NA

Currently, Port base vlan is initiated by PF and configured to its VFs,
by using command "ip link set <pf name> vf <vf id> vlan <vlan id>".
When a global reset was triggered, the hardware vlan table and the soft
recorded vlan information will be cleared by PF, and restored them until
VFs were ready. There is a short time window between the table had been
cleared and before table restored. If configured a new port base vlan tag
at this moment, driver will check the soft recorded vlan information,
and find there hasn't the old tag in it, which causing a warning print.

Due to the port base vlan is managed by PF, so the VFs's port base vlan
restoring should be handled by PF when PF was ready.

This patch fixes it.
Signed-off-by: NGuojia Liao <liaoguojia@huawei.com>
Reviewed-by: NPeng Li <lipeng321@huawei.com>
Reviewed-by: NZhong Zhaohui <zhongzhaohui@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 9a6f8237
...@@ -1714,6 +1714,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev) ...@@ -1714,6 +1714,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
vport->vf_info.link_state = IFLA_VF_LINK_STATE_AUTO; vport->vf_info.link_state = IFLA_VF_LINK_STATE_AUTO;
vport->mps = HCLGE_MAC_DEFAULT_FRAME; vport->mps = HCLGE_MAC_DEFAULT_FRAME;
vport->port_base_vlan_cfg.state = HNAE3_PORT_BASE_VLAN_DISABLE; vport->port_base_vlan_cfg.state = HNAE3_PORT_BASE_VLAN_DISABLE;
vport->port_base_vlan_cfg.tbl_sta = true;
vport->rxvlan_cfg.rx_vlan_offload_en = true; vport->rxvlan_cfg.rx_vlan_offload_en = true;
INIT_LIST_HEAD(&vport->vlan_list); INIT_LIST_HEAD(&vport->vlan_list);
INIT_LIST_HEAD(&vport->uc_mac_list); INIT_LIST_HEAD(&vport->uc_mac_list);
...@@ -6966,7 +6967,7 @@ int hclge_vport_start(struct hclge_vport *vport) ...@@ -6966,7 +6967,7 @@ int hclge_vport_start(struct hclge_vport *vport)
set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
vport->last_active_jiffies = jiffies; vport->last_active_jiffies = jiffies;
if (test_and_clear_bit(vport->vport_id, hdev->vport_config_block)) { if (test_bit(vport->vport_id, hdev->vport_config_block)) {
if (vport->vport_id) { if (vport->vport_id) {
hclge_restore_mac_table_common(vport); hclge_restore_mac_table_common(vport);
hclge_restore_vport_vlan_table(vport); hclge_restore_vport_vlan_table(vport);
...@@ -6974,6 +6975,8 @@ int hclge_vport_start(struct hclge_vport *vport) ...@@ -6974,6 +6975,8 @@ int hclge_vport_start(struct hclge_vport *vport)
hclge_restore_hw_table(hdev); hclge_restore_hw_table(hdev);
} }
} }
clear_bit(vport->vport_id, hdev->vport_config_block);
return 0; return 0;
} }
...@@ -8857,33 +8860,52 @@ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev) ...@@ -8857,33 +8860,52 @@ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
} }
} }
void hclge_restore_vport_vlan_table(struct hclge_vport *vport) void hclge_restore_vport_port_base_vlan_config(struct hclge_dev *hdev)
{ {
struct hclge_vport_vlan_cfg *vlan, *tmp; struct hclge_vlan_info *vlan_info;
struct hclge_dev *hdev = vport->back; struct hclge_vport *vport;
u16 vlan_proto; u16 vlan_proto;
u16 state, vlan_id; u16 vlan_id;
u16 state;
int vf_id;
int ret; int ret;
vlan_proto = vport->port_base_vlan_cfg.vlan_info.vlan_proto; /* PF should restore all vfs port base vlan */
vlan_id = vport->port_base_vlan_cfg.vlan_info.vlan_tag; for (vf_id = 0; vf_id < hdev->num_alloc_vfs; vf_id++) {
state = vport->port_base_vlan_cfg.state; vport = &hdev->vport[vf_id + HCLGE_VF_VPORT_START_NUM];
vlan_info = vport->port_base_vlan_cfg.tbl_sta ?
&vport->port_base_vlan_cfg.vlan_info :
&vport->port_base_vlan_cfg.old_vlan_info;
if (state != HNAE3_PORT_BASE_VLAN_DISABLE) { vlan_id = vlan_info->vlan_tag;
clear_bit(vport->vport_id, hdev->vlan_table[vlan_id]); vlan_proto = vlan_info->vlan_proto;
hclge_set_vlan_filter_hw(hdev, htons(vlan_proto), state = vport->port_base_vlan_cfg.state;
vport->vport_id, vlan_id,
false); if (state != HNAE3_PORT_BASE_VLAN_DISABLE) {
return; clear_bit(vport->vport_id, hdev->vlan_table[vlan_id]);
ret = hclge_set_vlan_filter_hw(hdev, htons(vlan_proto),
vport->vport_id,
vlan_id, false);
vport->port_base_vlan_cfg.tbl_sta = ret == 0;
}
} }
}
list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) { void hclge_restore_vport_vlan_table(struct hclge_vport *vport)
ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), {
vport->vport_id, struct hclge_vport_vlan_cfg *vlan, *tmp;
vlan->vlan_id, false); struct hclge_dev *hdev = vport->back;
if (ret) int ret;
break;
vlan->hd_tbl_status = true; if (vport->port_base_vlan_cfg.state == HNAE3_PORT_BASE_VLAN_DISABLE) {
list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
vport->vport_id,
vlan->vlan_id, false);
if (ret)
break;
vlan->hd_tbl_status = true;
}
} }
} }
...@@ -8924,6 +8946,7 @@ static int hclge_restore_hw_table(struct hclge_dev *hdev) ...@@ -8924,6 +8946,7 @@ static int hclge_restore_hw_table(struct hclge_dev *hdev)
struct hnae3_handle *handle = &vport->nic; struct hnae3_handle *handle = &vport->nic;
hclge_restore_mac_table_common(vport); hclge_restore_mac_table_common(vport);
hclge_restore_vport_port_base_vlan_config(hdev);
hclge_restore_vport_vlan_table(vport); hclge_restore_vport_vlan_table(vport);
set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state);
...@@ -8964,6 +8987,7 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport, ...@@ -8964,6 +8987,7 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport,
new_info->vlan_tag, new_info->vlan_tag,
false); false);
} }
vport->port_base_vlan_cfg.tbl_sta = false;
ret = hclge_set_vlan_filter_hw(hdev, htons(old_info->vlan_proto), ret = hclge_set_vlan_filter_hw(hdev, htons(old_info->vlan_proto),
vport->vport_id, old_info->vlan_tag, vport->vport_id, old_info->vlan_tag,
...@@ -8997,7 +9021,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, ...@@ -8997,7 +9021,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
false); false);
if (ret) if (ret)
return ret; return ret;
vport->port_base_vlan_cfg.tbl_sta = false;
/* remove old VLAN tag */ /* remove old VLAN tag */
ret = hclge_set_vlan_filter_hw(hdev, ret = hclge_set_vlan_filter_hw(hdev,
htons(old_vlan_info->vlan_proto), htons(old_vlan_info->vlan_proto),
...@@ -9023,9 +9047,16 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, ...@@ -9023,9 +9047,16 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE; nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
update: update:
vport->port_base_vlan_cfg.old_vlan_info.vlan_tag =
old_vlan_info->vlan_tag;
vport->port_base_vlan_cfg.old_vlan_info.qos =
old_vlan_info->qos;
vport->port_base_vlan_cfg.old_vlan_info.vlan_proto =
old_vlan_info->vlan_proto;
vport->port_base_vlan_cfg.vlan_info.vlan_tag = vlan_info->vlan_tag; vport->port_base_vlan_cfg.vlan_info.vlan_tag = vlan_info->vlan_tag;
vport->port_base_vlan_cfg.vlan_info.qos = vlan_info->qos; vport->port_base_vlan_cfg.vlan_info.qos = vlan_info->qos;
vport->port_base_vlan_cfg.vlan_info.vlan_proto = vlan_info->vlan_proto; vport->port_base_vlan_cfg.vlan_info.vlan_proto = vlan_info->vlan_proto;
vport->port_base_vlan_cfg.tbl_sta = true;
return 0; return 0;
} }
......
...@@ -905,7 +905,9 @@ struct hclge_vlan_info { ...@@ -905,7 +905,9 @@ struct hclge_vlan_info {
struct hclge_port_base_vlan_config { struct hclge_port_base_vlan_config {
u16 state; u16 state;
bool tbl_sta;
struct hclge_vlan_info vlan_info; struct hclge_vlan_info vlan_info;
struct hclge_vlan_info old_vlan_info;
}; };
struct hclge_vf_info { struct hclge_vf_info {
...@@ -1021,6 +1023,7 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, ...@@ -1021,6 +1023,7 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
enum HCLGE_MAC_ADDR_TYPE mac_type); enum HCLGE_MAC_ADDR_TYPE mac_type);
void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list); void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list);
void hclge_restore_mac_table_common(struct hclge_vport *vport); void hclge_restore_mac_table_common(struct hclge_vport *vport);
void hclge_restore_vport_port_base_vlan_config(struct hclge_dev *hdev);
void hclge_restore_vport_vlan_table(struct hclge_vport *vport); void hclge_restore_vport_vlan_table(struct hclge_vport *vport);
int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
struct hclge_vlan_info *vlan_info); struct hclge_vlan_info *vlan_info);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册