From: shenhao shenhao21@huawei.com
driver inclusion category: Feature bugzilla: NA CVE: NA
--------------------------------------------------- This patch adds support for extended VLAN mode, as we call dynamic vlan mode. In this mode, vf vlan filter will be switch between enable and disable, according to user configuration.
This patch also adds support for QOS in vlan 802.1Q protocol.
Signed-off-by: liaoguojia liaoguojia@huawei.com Signed-off-by: shenhao shenhao21@huawei.com Reviewed-by: Zhong Zhaohui zhongzhaohui@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 + drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 3 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 280 ++++++++++++++++----- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 8 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 9 - .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5 + 8 files changed, 239 insertions(+), 75 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 855274b..9882039 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -650,10 +650,12 @@ struct hnae3_unic_private_info { #define HNAE3_BPE BIT(2) /* broadcast promisc enable */ #define HNAE3_OVERFLOW_UPE BIT(3) /* unicast mac vlan overflow */ #define HNAE3_OVERFLOW_MPE BIT(4) /* multicast mac vlan overflow */ -#define HNAE3_VLAN_FLTR BIT(5) /* enable vlan filter */ +#define HNAE3_VLAN_FLTR BIT(5) /* enable vlan filter by promisc mode */ +#define HNAE3_VF_VLAN_EN BIT(6) /* enable vf vlan filter by vlan used */ #define HNAE3_UPE (HNAE3_USER_UPE | HNAE3_OVERFLOW_UPE) #define HNAE3_MPE (HNAE3_USER_MPE | HNAE3_OVERFLOW_MPE) #define HNAE3_OVERFLOW_UMPE (HNAE3_OVERFLOW_UPE | HNAE3_OVERFLOW_MPE) +#define HNAE3_VLAN_FLTR_EN (HNAE3_VLAN_FLTR | HNAE3_VF_VLAN_EN)
struct hnae3_handle { struct hnae3_client *client; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 74499a5..eb24440 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -583,6 +583,7 @@ static int hns3_nic_mc_unsync(struct net_device *netdev,
static u8 hns3_get_netdev_flags(struct net_device *netdev) { + struct hnae3_handle *h = hns3_get_handle(netdev); u8 flags = 0;
if (netdev->flags & IFF_PROMISC) { @@ -593,6 +594,8 @@ static u8 hns3_get_netdev_flags(struct net_device *netdev) flags |= HNAE3_USER_MPE; }
+ flags |= (h->netdev_flags & HNAE3_VF_VLAN_EN); + return flags; }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 5e7bf03..1ecbc1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -115,7 +115,8 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) } else { /* recover promisc mode before loopback test */ hns3_request_update_promisc_mode(h); - vlan_filter_enable = ndev->flags & IFF_PROMISC ? false : true; + vlan_filter_enable = (h->netdev_flags & HNAE3_VLAN_FLTR_EN) ? + false : true; hns3_enable_vlan_filter(ndev, vlan_filter_enable); }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 5bcc30d..1e35d89 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -494,6 +494,8 @@ struct hclge_pf_res_cmd { #define HCLGE_CFG_RSS_SIZE_M GENMASK(31, 24) #define HCLGE_CFG_SPEED_ABILITY_S 0 #define HCLGE_CFG_SPEED_ABILITY_M GENMASK(7, 0) +#define HCLGE_CFG_VLAN_MODE_S 8 +#define HCLGE_CFG_VLAN_MODE_M GENMASK(9, 8) #define HCLGE_CFG_UMV_TBL_SPACE_S 16 #define HCLGE_CFG_UMV_TBL_SPACE_M GENMASK(31, 16)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index aaf3512..cfec96f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -70,6 +70,7 @@ static void hclge_sync_mac_table(struct hclge_dev *hdev); static int hclge_restore_hw_table(struct hclge_dev *hdev); static void hclge_sync_promisc_mode(struct hclge_dev *hdev); +static int hclge_vf_vlan_filter_switch(struct hclge_vport *vport);
struct hnae3_ae_algo ae_algo;
@@ -1305,6 +1306,9 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc) cfg->speed_ability = hnae3_get_field(__le32_to_cpu(req->param[1]), HCLGE_CFG_SPEED_ABILITY_M, HCLGE_CFG_SPEED_ABILITY_S); + cfg->vlan_mode_sel = hnae3_get_field(__le32_to_cpu(req->param[1]), + HCLGE_CFG_VLAN_MODE_M, + HCLGE_CFG_VLAN_MODE_S); cfg->umv_space = hnae3_get_field(__le32_to_cpu(req->param[1]), HCLGE_CFG_UMV_TBL_SPACE_M, HCLGE_CFG_UMV_TBL_SPACE_S); @@ -1406,6 +1410,7 @@ static int hclge_configure(struct hclge_dev *hdev) hdev->tc_max = cfg.tc_num; hdev->tm_info.hw_pfc_map = 0; hdev->wanted_umv_size = cfg.umv_space; + hdev->vlan_mode = cfg.vlan_mode_sel;
if (hnae3_dev_fd_supported(hdev)) { hdev->fd_en = true; @@ -8268,6 +8273,18 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd); }
+#define HCLGE_FILTER_TYPE_VF 0 +#define HCLGE_FILTER_TYPE_PORT 1 +#define HCLGE_FILTER_FE_EGRESS_V1_B BIT(0) +#define HCLGE_FILTER_FE_NIC_INGRESS_B BIT(0) +#define HCLGE_FILTER_FE_NIC_EGRESS_B BIT(1) +#define HCLGE_FILTER_FE_ROCE_INGRESS_B BIT(2) +#define HCLGE_FILTER_FE_ROCE_EGRESS_B BIT(3) +#define HCLGE_FILTER_FE_EGRESS (HCLGE_FILTER_FE_NIC_EGRESS_B \ + | HCLGE_FILTER_FE_ROCE_EGRESS_B) +#define HCLGE_FILTER_FE_INGRESS (HCLGE_FILTER_FE_NIC_INGRESS_B \ + | HCLGE_FILTER_FE_ROCE_INGRESS_B) + static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, u8 fe_type, bool filter_en, u8 vf_id) { @@ -8275,33 +8292,40 @@ static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, struct hclge_desc desc; int ret;
- hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, false); + /* if vlan_mode set as dynamic mode, + * port vlan filter needn't to enable + */ + if (vlan_type == HCLGE_FILTER_TYPE_PORT && + hdev->vlan_mode == HCLGE_VLAN_DYNAMIC_MODE) + return 0; + + /* read current vlan filter parameter */ + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, true);
req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data; req->vlan_type = vlan_type; - req->vlan_fe = filter_en ? fe_type : 0; req->vf_id = vf_id;
ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get vlan filter config, ret = %d.\n", ret); + return ret; + } + + /* modify and write new config parameter */ + hclge_cmd_reuse_desc(&desc, false); + req->vlan_fe = filter_en ? + (req->vlan_fe | fe_type) : (req->vlan_fe & ~fe_type); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) - dev_err(&hdev->pdev->dev, "set vlan filter fail, ret =%d.\n", + dev_err(&hdev->pdev->dev, "failed to set vlan filter, ret = %d.\n", ret);
return ret; }
-#define HCLGE_FILTER_TYPE_VF 0 -#define HCLGE_FILTER_TYPE_PORT 1 -#define HCLGE_FILTER_FE_EGRESS_V1_B BIT(0) -#define HCLGE_FILTER_FE_NIC_INGRESS_B BIT(0) -#define HCLGE_FILTER_FE_NIC_EGRESS_B BIT(1) -#define HCLGE_FILTER_FE_ROCE_INGRESS_B BIT(2) -#define HCLGE_FILTER_FE_ROCE_EGRESS_B BIT(3) -#define HCLGE_FILTER_FE_EGRESS (HCLGE_FILTER_FE_NIC_EGRESS_B \ - | HCLGE_FILTER_FE_ROCE_EGRESS_B) -#define HCLGE_FILTER_FE_INGRESS (HCLGE_FILTER_FE_NIC_INGRESS_B \ - | HCLGE_FILTER_FE_ROCE_INGRESS_B) - static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); @@ -8443,6 +8467,41 @@ static int hclge_set_port_vlan_filter(struct hclge_dev *hdev, __be16 proto, return ret; }
+static bool hclge_need_update_port_vlan(struct hclge_dev *hdev, u16 vport_id, + u16 vlan_id, bool is_kill) +{ + /* vlan 0 may be added twice when 8021q module is enabled */ + if (!is_kill && !vlan_id && + test_bit(vport_id, hdev->vlan_table[vlan_id])) + return false; + + if (!is_kill && test_and_set_bit(vport_id, hdev->vlan_table[vlan_id])) { + dev_warn(&hdev->pdev->dev, + "Add port vlan failed, vport %u is already in vlan %u\n", + vport_id, vlan_id); + return false; + } + + /* if the vlan id is not in the port vlan table, just return 0, it's + * unnecessary to retry. + */ + if (is_kill && + !test_and_clear_bit(vport_id, hdev->vlan_table[vlan_id])) { + dev_warn(&hdev->pdev->dev, + "Delete port vlan failed, vport %u is not in vlan %u\n", + vport_id, vlan_id); + return false; + } + + /* if vlan mode set as HCLGE_VLAN_DYNAMIC_MODE, + * needn't to write the vlan tag to port vlan fitler + */ + if (hdev->vlan_mode == HCLGE_VLAN_DYNAMIC_MODE) + return false; + + return true; +} + static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, u16 vport_id, u16 vlan_id, bool is_kill) @@ -8462,26 +8521,9 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, return ret; }
- /* vlan 0 may be added twice when 8021q module is enabled */ - if (!is_kill && !vlan_id && - test_bit(vport_id, hdev->vlan_table[vlan_id])) + if (!hclge_need_update_port_vlan(hdev, vport_id, vlan_id, is_kill)) return 0;
- if (!is_kill && test_and_set_bit(vport_id, hdev->vlan_table[vlan_id])) { - dev_err(&hdev->pdev->dev, - "Add port vlan failed, vport %u is already in vlan %u\n", - vport_id, vlan_id); - return -EINVAL; - } - - if (is_kill && - !test_and_clear_bit(vport_id, hdev->vlan_table[vlan_id])) { - dev_err(&hdev->pdev->dev, - "Delete port vlan failed, vlan %u is not in vport %u\n", - vlan_id, vport_id); - return -EINVAL; - } - for_each_set_bit(vport_idx, hdev->vlan_table[vlan_id], HCLGE_VPORT_NUM) vport_num++;
@@ -8573,7 +8615,7 @@ static int hclge_set_vlan_rx_offload_cfg(struct hclge_vport *vport)
static int hclge_vlan_offload_cfg(struct hclge_vport *vport, u16 port_base_vlan_state, - u16 vlan_tag) + u16 vlan_tag, u8 qos) { int ret;
@@ -8584,7 +8626,8 @@ static int hclge_vlan_offload_cfg(struct hclge_vport *vport, } else { vport->txvlan_cfg.accept_tag1 = false; vport->txvlan_cfg.insert_tag1_en = true; - vport->txvlan_cfg.default_tag1 = vlan_tag; + vport->txvlan_cfg.default_tag1 = (qos << VLAN_PRIO_SHIFT) | + vlan_tag; }
vport->txvlan_cfg.accept_untag1 = true; @@ -8671,6 +8714,12 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev) /* for revision 0x21, vf vlan filter is per function */ for (i = 0; i < hdev->num_alloc_vport; i++) { vport = &hdev->vport[i]; + vport->vf_vlan_en = + hdev->vlan_mode == HCLGE_VLAN_DEFAULT_MODE; + + if (!vport->vf_vlan_en) + continue; + ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, HCLGE_FILTER_FE_EGRESS, @@ -8708,13 +8757,15 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
for (i = 0; i < hdev->num_alloc_vport; i++) { u16 vlan_tag; + u8 qos;
vport = &hdev->vport[i]; vlan_tag = vport->port_base_vlan_cfg.vlan_info.vlan_tag; + qos = vport->port_base_vlan_cfg.vlan_info.qos;
ret = hclge_vlan_offload_cfg(vport, vport->port_base_vlan_cfg.state, - vlan_tag); + vlan_tag, qos); if (ret) return ret; } @@ -8873,6 +8924,7 @@ void hclge_restore_vport_vlan_table(struct hclge_vport *vport) vlan->hd_tbl_status = true; } } + hclge_vf_vlan_filter_switch(vport); }
/* For global reset and imp reset, hardware will clear the mac table, @@ -8937,6 +8989,51 @@ int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) return hclge_set_vlan_rx_offload_cfg(vport); }
+static bool hclge_has_vlan_used(struct hclge_dev *hdev, u16 vport_id) +{ +#define VLAN_CHECK_START_NUM 1 + u16 vlan_id; + + /* if set as vlan normal mode, vf vlan filter always on */ + if (hdev->vlan_mode == HCLGE_VLAN_DEFAULT_MODE) + return true; + + /* check all vlan tag in vf vlan table except 0 */ + for (vlan_id = VLAN_CHECK_START_NUM; vlan_id < VLAN_N_VID; vlan_id++) + if (test_bit(vport_id, hdev->vlan_table[vlan_id])) + return true; + + return false; +} + +static int hclge_vf_vlan_filter_switch(struct hclge_vport *vport) +{ + struct hnae3_handle *nic = &vport->nic; + struct hclge_dev *hdev = vport->back; + u8 filter_en; + int ret; + + filter_en = hclge_has_vlan_used(hdev, vport->vport_id) || + vport->port_base_vlan_cfg.state == HNAE3_PORT_BASE_VLAN_ENABLE; + + if (filter_en == vport->vf_vlan_en) + return 0; + + ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, + HCLGE_FILTER_FE_EGRESS, + filter_en, vport->vport_id); + if (ret) + return ret; + + vport->vf_vlan_en = filter_en; + if (filter_en) + nic->netdev_flags |= HNAE3_VF_VLAN_EN; + else + nic->netdev_flags &= ~HNAE3_VF_VLAN_EN; + + return 0; +} + static int hclge_update_vlan_filter_entries(struct hclge_vport *vport, u16 port_base_vlan_state, struct hclge_vlan_info *new_info, @@ -8947,6 +9044,9 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport,
if (port_base_vlan_state == HNAE3_PORT_BASE_VLAN_ENABLE) { hclge_rm_vport_all_vlan_table(vport, false); + /* force clear vlan 0 */ + hclge_set_vf_vlan_common(hdev, vport->vport_id, true, 0, + htons(ETH_P_8021Q)); return hclge_set_vlan_filter_hw(hdev, htons(new_info->vlan_proto), vport->vport_id, @@ -8974,10 +9074,15 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
old_vlan_info = &vport->port_base_vlan_cfg.vlan_info;
- ret = hclge_vlan_offload_cfg(vport, state, vlan_info->vlan_tag); + ret = hclge_vlan_offload_cfg(vport, state, vlan_info->vlan_tag, + vlan_info->qos); if (ret) return ret;
+ /* if needn't to update vlan tag, return */ + if (old_vlan_info->vlan_tag == vlan_info->vlan_tag) + goto update; + if (state == HNAE3_PORT_BASE_VLAN_MODIFY) { /* add new VLAN tag */ ret = hclge_set_vlan_filter_hw(hdev, @@ -8989,13 +9094,22 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, return ret; vport->port_base_vlan_cfg.tbl_sta = false; /* remove old VLAN tag */ - ret = hclge_set_vlan_filter_hw(hdev, - htons(old_vlan_info->vlan_proto), - vport->vport_id, - old_vlan_info->vlan_tag, - true); - if (ret) + if (old_vlan_info->vlan_tag == 0) + ret = hclge_set_vf_vlan_common(hdev, vport->vport_id, + true, 0, + htons(ETH_P_8021Q)); + else + ret = hclge_set_vlan_filter_hw(hdev, + htons(ETH_P_8021Q), + vport->vport_id, + old_vlan_info->vlan_tag, + true); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to clear vport%u port base vlan %u, ret = %d.\n", + vport->vport_id, old_vlan_info->vlan_tag, ret); return ret; + }
goto update; } @@ -9024,25 +9138,26 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, vport->port_base_vlan_cfg.vlan_info.vlan_proto = vlan_info->vlan_proto; vport->port_base_vlan_cfg.tbl_sta = true;
- return 0; + return hclge_vf_vlan_filter_switch(vport); }
static u16 hclge_get_port_base_vlan_state(struct hclge_vport *vport, enum hnae3_port_base_vlan_state state, - u16 vlan) + u16 vlan, u8 qos) { if (state == HNAE3_PORT_BASE_VLAN_DISABLE) { - if (!vlan) + if (!vlan && !qos) return HNAE3_PORT_BASE_VLAN_NOCHANGE; - else - return HNAE3_PORT_BASE_VLAN_ENABLE; + + return HNAE3_PORT_BASE_VLAN_ENABLE; } else { - if (!vlan) + if (!vlan && !qos) return HNAE3_PORT_BASE_VLAN_DISABLE; - else if (vport->port_base_vlan_cfg.vlan_info.vlan_tag == vlan) + if (vport->port_base_vlan_cfg.vlan_info.vlan_tag == vlan && + vport->port_base_vlan_cfg.vlan_info.qos == qos) return HNAE3_PORT_BASE_VLAN_NOCHANGE; - else - return HNAE3_PORT_BASE_VLAN_MODIFY; + + return HNAE3_PORT_BASE_VLAN_MODIFY; } }
@@ -9070,7 +9185,7 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
state = hclge_get_port_base_vlan_state(vport, vport->port_base_vlan_cfg.state, - vlan); + vlan, qos); if (state == HNAE3_PORT_BASE_VLAN_NOCHANGE) return 0;
@@ -9078,16 +9193,43 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid, vlan_info.qos = qos; vlan_info.vlan_proto = ntohs(proto);
- 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], - vport->vport_id, state, - vlan, qos, - ntohs(proto)); + ret = hclge_update_port_base_vlan_cfg(vport, state, &vlan_info); + if (ret) { + dev_err(&hdev->pdev->dev, + "update port base vlan for vf %d failed, ret = %d\n", + vfid, ret); return ret; } + + if (test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) + return hclge_push_vf_port_base_vlan_info(&hdev->vport[0], + vport->vport_id, + state, vlan, qos, + ntohs(proto)); + + return 0; +} + +static void hclge_clear_vf_vlan(struct hclge_dev *hdev) +{ + struct hclge_vlan_info *vlan_info; + struct hclge_vport *vport; + int ret; + int vf; + + /* clear port base vlan for all vf */ + for (vf = HCLGE_VF_VPORT_START_NUM; vf < hdev->num_alloc_vport; vf++) { + vport = &hdev->vport[vf]; + vlan_info = &vport->port_base_vlan_cfg.vlan_info; + + ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), + vport->vport_id, + vlan_info->vlan_tag, true); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to clear vf vlan for vf%d, ret = %d.\n", + vf - HCLGE_VF_VPORT_START_NUM, ret); + } }
int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, @@ -9132,7 +9274,13 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, */ set_bit(vlan_id, vport->vlan_del_fail_bmap); } - return ret; + + if (ret) { + dev_info(&hdev->pdev->dev, "failed to set vf vlan, ret = %d!\n", + ret); + } + + return hclge_vf_vlan_filter_switch(vport); }
static void hclge_sync_vlan_filter(struct hclge_dev *hdev) @@ -10528,6 +10676,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) struct hclge_mac *mac = &hdev->hw.mac;
hclge_reset_vf_rate(hdev); + hclge_clear_vf_vlan(hdev); hclge_misc_affinity_teardown(hdev); hclge_state_uninit(hdev); hclge_uninit_vport_mac_table(hdev); @@ -11162,6 +11311,7 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) struct hclge_vport *vport = &hdev->vport[0]; struct hnae3_handle *handle = &vport->nic; u8 tmp_flags = 0; + u32 filter_en; int ret;
if (vport->last_promisc_flags != vport->overflow_promisc_flags) { @@ -11175,8 +11325,10 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) tmp_flags & HNAE3_MPE); if (!ret) { clear_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); - hclge_enable_vlan_filter(handle, - tmp_flags & HNAE3_VLAN_FLTR); + /* promisc set for pf, so vport id as 0 */ + filter_en = hclge_has_vlan_used(hdev, 0) ? + HNAE3_VLAN_FLTR : 0; + hclge_enable_vlan_filter(handle, tmp_flags & filter_en); } } } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index ff4d7d1..c03e43c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -316,6 +316,11 @@ enum hclge_fc_mode { HCLGE_FC_DEFAULT };
+enum hclge_vlan_mode_sel { + HCLGE_VLAN_DEFAULT_MODE, + HCLGE_VLAN_DYNAMIC_MODE, +}; + enum hclge_link_fail_code { HCLGE_LF_NORMAL, HCLGE_LF_REF_CLOCK_LOST, @@ -353,6 +358,7 @@ struct hclge_cfg { u8 default_speed; u32 numa_node_map; u8 speed_ability; + u8 vlan_mode_sel; u16 umv_space; };
@@ -829,6 +835,7 @@ struct hclge_dev { unsigned long fd_bmap[BITS_TO_LONGS(MAX_FD_FILTER_NUM)]; enum HCLGE_FD_ACTIVE_RULE_TYPE fd_active_type; u8 fd_en; + u8 vlan_mode;
u16 wanted_umv_size; /* max available unicast mac vlan space */ @@ -935,6 +942,7 @@ struct hclge_vport { u32 bw_limit; /* VSI BW Limit (0 = disabled) */ u8 dwrr;
+ u8 vf_vlan_en; unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)]; struct list_head vlan_list; /* Store VF vlan table */ struct hclge_port_base_vlan_config port_base_vlan_cfg; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index bc86207..d55b999 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -488,15 +488,6 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport, bool en = msg_cmd->is_kill ? true : false;
status = hclge_en_hw_strip_rxvtag(handle, en); - } else if (msg_cmd->subcode == HCLGE_MBX_PORT_BASE_VLAN_CFG) { - struct hclge_vlan_info *vlan_info; - u16 *state; - - state = (u16 *)&mbx_req->msg.data[HCLGE_MBX_VLAN_STATE_OFFSET]; - vlan_info = (struct hclge_vlan_info *) - &mbx_req->msg.data[HCLGE_MBX_VLAN_INFO_OFFSET]; - status = hclge_update_port_base_vlan_cfg(vport, *state, - vlan_info); } else if (msg_cmd->subcode == HCLGE_MBX_GET_PORT_BASE_VLAN_STATE) { resp_msg->data[0] = vport->port_base_vlan_cfg.state; resp_msg->len = sizeof(u8); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index f758a0c..76fabe1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2940,6 +2940,11 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) return ret; }
+ /* get current port based vlan state from PF */ + ret = hclgevf_get_port_base_vlan_filter_state(hdev); + if (ret) + return ret; + set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
dev_info(&hdev->pdev->dev, "Reset done\n");