From: Jian Shen shenjian15@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
As the HNS3 driver doesn't update the mac address directly in function hns3_set_rx_mode() now, it can't know whether the mac table is full from __dev_uc_sync() and __dev_mc_sync(), so it's senseless to handle the overflow promisc here.
This patch removes the handle of overflow promisc from function hns3_set_rx_mode(), and updates the promisc mode in the service task.
This patch also fixes a vlan id restore twice issue, and add debugfs support for query mac list, So it need to be split before upstream.
Signed-off-by: Jian Shen shenjian15@huawei.com Reviewed-by: Peng Li lipeng321@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_debugfs.c | 2 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 33 ++-- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 2 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 51 +++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 208 ++++++++++++++------- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 6 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 7 +- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 26 +++ .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + 11 files changed, 244 insertions(+), 97 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 92854cc..ad1274e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -272,6 +272,8 @@ struct hnae3_ae_dev { * Set loopback * set_promisc_mode * Set promisc mode + * request_update_promisc_mode + * request to hclge(vf) to update promisc mode * set_mtu() * set mtu * get_pauseparam() @@ -402,6 +404,7 @@ struct hnae3_ae_ops {
int (*set_promisc_mode)(struct hnae3_handle *handle, bool en_uc_pmc, bool en_mc_pmc); + void (*request_update_promisc_mode)(struct hnae3_handle *handle); int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
void (*get_pauseparam)(struct hnae3_handle *handle, @@ -646,6 +649,7 @@ struct hnae3_unic_private_info { #define HNAE3_VLAN_FLTR BIT(5) /* enable vlan filter */ #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)
struct hnae3_handle { struct hnae3_client *client; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index c8681c5..0babf50 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -260,6 +260,8 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump m7 info\n"); dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); + dev_info(&h->pdev->dev, "dump uc mac list <func id>\n"); + dev_info(&h->pdev->dev, "dump mc mac list <func id>\n");
memset(printf_buf, 0, HNS3_DBG_BUF_LEN); strncat(printf_buf, "dump reg [[bios common] [ssu <port_id>]", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9c79f46d..2b22c0e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -598,34 +598,25 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev) { struct hnae3_handle *h = hns3_get_handle(netdev); u8 new_flags; - int ret;
new_flags = hns3_get_netdev_flags(netdev);
- ret = __dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync); - if (ret) { - netdev_err(netdev, "sync uc address fail\n"); - if (ret == -ENOSPC) - new_flags |= HNAE3_OVERFLOW_UPE; - } - - if (netdev->flags & IFF_MULTICAST) { - ret = __dev_mc_sync(netdev, hns3_nic_mc_sync, - hns3_nic_mc_unsync); - if (ret) { - netdev_err(netdev, "sync mc address fail\n"); - if (ret == -ENOSPC) - new_flags |= HNAE3_OVERFLOW_MPE; - } - } + __dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync); + __dev_mc_sync(netdev, hns3_nic_mc_sync, hns3_nic_mc_unsync);
/* User mode Promisc mode enable and vlan filtering is disabled to - * let all packets in. MAC-VLAN Table overflow Promisc enabled and - * vlan fitering is enabled + * let all packets in. */ - hns3_enable_vlan_filter(netdev, new_flags & HNAE3_VLAN_FLTR); h->netdev_flags = new_flags; - hns3_update_promisc_mode(netdev, new_flags); + hns3_request_update_promisc_mode(h); +} + +void hns3_request_update_promisc_mode(struct hnae3_handle *handle) +{ + const struct hnae3_ae_ops *ops = handle->ae_algo->ops; + + if (ops->request_update_promisc_mode) + ops->request_update_promisc_mode(handle); }
int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 98cd8a1..c194ab9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -648,6 +648,7 @@ void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
void hns3_enable_vlan_filter(struct net_device *netdev, bool enable); int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags); +void hns3_request_update_promisc_mode(struct hnae3_handle *handle);
#ifdef CONFIG_HNS3_DCB void hns3_dcbnl_setup(struct hnae3_handle *handle); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index feffd1d..37ce34b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -104,7 +104,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) h->ae_algo->ops->set_promisc_mode(h, true, true); } else { /* recover promisc mode before loopback test */ - hns3_update_promisc_mode(ndev, h->netdev_flags); + hns3_request_update_promisc_mode(h); vlan_filter_enable = ndev->flags & IFF_PROMISC ? false : true; hns3_enable_vlan_filter(ndev, vlan_filter_enable); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 635b4f0..f756721 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1279,6 +1279,49 @@ static void hclge_dbg_dump_qs_shaper(struct hclge_dev *hdev, hclge_dbg_dump_qs_shaper_single(hdev, qsid); }
+static int hclge_dbg_dump_mac_list(struct hclge_dev *hdev, const char *cmd_buf, + bool is_unicast) +{ + struct hclge_vport_mac_addr_cfg *mac_node, *tmp; + struct hclge_vport *vport; + struct list_head *list; + u32 func_id; + int ret; + + ret = kstrtouint(cmd_buf, 0, &func_id); + if (ret < 0) { + dev_err(&hdev->pdev->dev, + "dump mac list: bad command string, ret=%d\n", ret); + return -EINVAL; + } + + if (func_id >= hdev->num_alloc_vport) { + dev_err(&hdev->pdev->dev, + "function id(%u) is out of range(0-%u)\n", func_id, + hdev->num_alloc_vport - 1); + return -EINVAL; + } + + vport = &hdev->vport[func_id]; + + list = is_unicast ? &vport->uc_mac_list : &vport->mc_mac_list; + + dev_info(&hdev->pdev->dev, "vport %u %s mac list:\n", + func_id, is_unicast ? "uc" : "mc"); + dev_info(&hdev->pdev->dev, "mac address state\n"); + + spin_lock_bh(&vport->mac_list_lock); + + list_for_each_entry_safe(mac_node, tmp, list, node) { + dev_info(&hdev->pdev->dev, "%pM %d\n", + mac_node->mac_addr, mac_node->state); + } + + spin_unlock_bh(&vport->mac_list_lock); + + return 0; +} + int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { #define DUMP_REG "dump reg" @@ -1318,6 +1361,14 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { hclge_dbg_dump_qs_shaper(hdev, &cmd_buf[sizeof("dump qs shaper")]); + } else if (strncmp(cmd_buf, "dump uc mac list", 16) == 0) { + hclge_dbg_dump_mac_list(hdev, + &cmd_buf[sizeof("dump uc mac list")], + true); + } else if (strncmp(cmd_buf, "dump mc mac list", 16) == 0) { + hclge_dbg_dump_mac_list(hdev, + &cmd_buf[sizeof("dump mc mac list")], + false); } else { dev_info(&hdev->pdev->dev, "unknown command\n"); return -EINVAL; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 02f35fc..2f0025a 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);
struct hnae3_ae_algo ae_algo;
@@ -3738,15 +3739,7 @@ static int hclge_reset_stack(struct hclge_dev *hdev) if (ret) return ret;
- ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); - if (ret) - return ret; - - /* imp rest and global reset need to restore PF tbl */ - if (hdev->reset_type == HNAE3_IMP_RESET || - hdev->reset_type == HNAE3_GLOBAL_RESET) - return hclge_restore_hw_table(hdev); - return 0; + return hclge_notify_client(hdev, HNAE3_INIT_CLIENT); }
static void hclge_reset(struct hclge_dev *hdev) @@ -4048,6 +4041,7 @@ static void hclge_periodical_service_task(struct hclge_dev *hdev) */ hclge_update_link_status(hdev); hclge_sync_mac_table(hdev); + hclge_sync_promisc_mode(hdev);
if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) { delta = jiffies - hdev->last_serv_processed; @@ -4797,7 +4791,8 @@ static int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev, ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) dev_err(&hdev->pdev->dev, - "Set promisc mode fail, status is %d.\n", ret); + "Set vport %d promisc mode fail, ret = %d.\n", + param->vf_id, ret);
return ret; } @@ -4847,6 +4842,14 @@ static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc, en_bc_pmc); }
+static void hclge_request_update_promisc_mode(struct hnae3_handle *handle) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + + set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); +} + static int hclge_get_fd_mode(struct hclge_dev *hdev, u8 *fd_mode) { struct hclge_get_fd_mode_cmd *req; @@ -6985,11 +6988,13 @@ int hclge_vport_start(struct hclge_vport *vport) set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); vport->last_active_jiffies = jiffies;
- /* when received vport start mbx, it means the VF is start now */ - if (test_and_clear_bit(HCLGE_VPORT_STATE_BLOCK_CONFIG, &vport->state) || - test_and_clear_bit(vport->vport_id, hdev->need_restore_vf_table)) { - hclge_restore_mac_table_common(vport); - hclge_restore_vport_vlan_table(vport); + if (test_and_clear_bit(vport->vport_id, hdev->vport_config_block)) { + if (vport->vport_id) { + hclge_restore_mac_table_common(vport); + hclge_restore_vport_vlan_table(vport); + } else { + hclge_restore_hw_table(hdev); + } } return 0; } @@ -7426,6 +7431,8 @@ int hclge_update_mac_list(struct hclge_vport *vport,
set_bit(HCLGE_VPORT_STATE_MAC_TBL_CHANGE, &vport->state);
+ spin_lock_bh(&vport->mac_list_lock); + /* if the mac addr is already in the mac list, no need to add a new * one into it, just check the mac addr state, convert it to a new * new state, or just remove it, or do nothing. @@ -7433,21 +7440,28 @@ int hclge_update_mac_list(struct hclge_vport *vport, mac_node = hclge_find_mac_node(list, addr); if (mac_node) { hclge_mac_node_convert(mac_node, state); + spin_unlock_bh(&vport->mac_list_lock); return 0; }
/* if this address is never added, unnecessary to delete */ - if (state == HCLGE_MAC_TO_DEL) + if (state == HCLGE_MAC_TO_DEL) { + spin_unlock_bh(&vport->mac_list_lock); return -ENOENT; + }
mac_node = kzalloc(sizeof(*mac_node), GFP_ATOMIC); - if (!mac_node) + if (!mac_node) { + spin_unlock_bh(&vport->mac_list_lock); return -ENOMEM; + }
mac_node->state = state; ether_addr_copy(mac_node->mac_addr, addr); list_add_tail(&mac_node->node, list);
+ spin_unlock_bh(&vport->mac_list_lock); + return 0; }
@@ -7455,14 +7469,9 @@ static int hclge_add_uc_addr(struct hnae3_handle *handle, const unsigned char *addr) { struct hclge_vport *vport = hclge_get_vport(handle); - int ret; - - spin_lock_bh(&vport->mac_list_lock); - ret = hclge_update_mac_list(vport, HCLGE_MAC_TO_ADD, HCLGE_MAC_ADDR_UC, - addr); - spin_unlock_bh(&vport->mac_list_lock);
- return ret; + return hclge_update_mac_list(vport, HCLGE_MAC_TO_ADD, HCLGE_MAC_ADDR_UC, + addr); }
int hclge_add_uc_addr_common(struct hclge_vport *vport, @@ -7512,8 +7521,9 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport, } mutex_unlock(&hdev->vport_lock);
- dev_err(&hdev->pdev->dev, "UC MAC table full(%u)\n", - hdev->priv_umv_size); + if (!(vport->overflow_promisc_flags & HNAE3_OVERFLOW_UPE)) + dev_err(&hdev->pdev->dev, "UC MAC table full(%u)\n", + hdev->priv_umv_size);
return -ENOSPC; } @@ -7536,14 +7546,9 @@ static int hclge_rm_uc_addr(struct hnae3_handle *handle, const unsigned char *addr) { struct hclge_vport *vport = hclge_get_vport(handle); - int ret;
- spin_lock_bh(&vport->mac_list_lock); - ret = hclge_update_mac_list(vport, HCLGE_MAC_TO_DEL, HCLGE_MAC_ADDR_UC, - addr); - spin_unlock_bh(&vport->mac_list_lock); - - return ret; + return hclge_update_mac_list(vport, HCLGE_MAC_TO_DEL, HCLGE_MAC_ADDR_UC, + addr); }
int hclge_rm_uc_addr_common(struct hclge_vport *vport, @@ -7581,14 +7586,9 @@ static int hclge_add_mc_addr(struct hnae3_handle *handle, const unsigned char *addr) { struct hclge_vport *vport = hclge_get_vport(handle); - int ret;
- spin_lock_bh(&vport->mac_list_lock); - ret = hclge_update_mac_list(vport, HCLGE_MAC_TO_ADD, HCLGE_MAC_ADDR_MC, - addr); - spin_unlock_bh(&vport->mac_list_lock); - - return ret; + return hclge_update_mac_list(vport, HCLGE_MAC_TO_ADD, HCLGE_MAC_ADDR_MC, + addr); }
int hclge_add_mc_addr_common(struct hclge_vport *vport, @@ -7620,8 +7620,11 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport, return status; status = hclge_add_mac_vlan_tbl(vport, &req, desc);
- if (status == -ENOSPC) + /* if already overflow, not to print each time */ + if (status == -ENOSPC && + !(vport->overflow_promisc_flags & HNAE3_OVERFLOW_MPE)) { dev_err(&hdev->pdev->dev, "mc mac vlan table is full\n"); + }
return status; } @@ -7630,14 +7633,9 @@ static int hclge_rm_mc_addr(struct hnae3_handle *handle, const unsigned char *addr) { struct hclge_vport *vport = hclge_get_vport(handle); - int ret; - - spin_lock_bh(&vport->mac_list_lock); - ret = hclge_update_mac_list(vport, HCLGE_MAC_TO_DEL, HCLGE_MAC_ADDR_MC, - addr); - spin_unlock_bh(&vport->mac_list_lock);
- return ret; + return hclge_update_mac_list(vport, HCLGE_MAC_TO_DEL, HCLGE_MAC_ADDR_MC, + addr); }
int hclge_rm_mc_addr_common(struct hclge_vport *vport, @@ -7721,12 +7719,16 @@ static void hclge_unsync_mac_list(struct hclge_vport *vport, } }
-static void hclge_sync_from_add_list(struct list_head *add_list, +static bool hclge_sync_from_add_list(struct list_head *add_list, struct list_head *mac_list) { struct hclge_vport_mac_addr_cfg *mac_node, *tmp, *new_node; + bool all_added = true;
list_for_each_entry_safe(mac_node, tmp, add_list, node) { + if (mac_node->state == HCLGE_MAC_TO_ADD) + all_added = false; + /* if the mac address from tmp_add_list is not in the * uc/mc_mac_list, it means have received a TO_DEL request * during the time window of adding the mac address into mac @@ -7749,6 +7751,7 @@ static void hclge_sync_from_add_list(struct list_head *add_list, kfree(mac_node); } } + return all_added; }
static void hclge_sync_from_del_list(struct list_head *del_list, @@ -7788,12 +7791,30 @@ static void hclge_rollback_del_list(struct list_head *del_list, } }
+static void hclge_update_overflow_flags(struct hclge_vport *vport, + enum HCLGE_MAC_ADDR_TYPE mac_type, + bool is_all_added) +{ + if (mac_type == HCLGE_MAC_ADDR_UC) { + if (is_all_added) + vport->overflow_promisc_flags &= ~HNAE3_OVERFLOW_UPE; + else + vport->overflow_promisc_flags |= HNAE3_OVERFLOW_UPE; + } else { + if (is_all_added) + vport->overflow_promisc_flags &= ~HNAE3_OVERFLOW_MPE; + else + vport->overflow_promisc_flags |= HNAE3_OVERFLOW_MPE; + } +} + static void hclge_sync_vport_mac_table(struct hclge_vport *vport, enum HCLGE_MAC_ADDR_TYPE mac_type) { struct hclge_vport_mac_addr_cfg *mac_node, *tmp, *new_node; struct list_head tmp_add_list, tmp_del_list; struct list_head *list; + bool all_added;
INIT_LIST_HEAD(&tmp_add_list); INIT_LIST_HEAD(&tmp_del_list); @@ -7847,9 +7868,12 @@ static void hclge_sync_vport_mac_table(struct hclge_vport *vport, spin_lock_bh(&vport->mac_list_lock);
hclge_sync_from_del_list(&tmp_del_list, list); - hclge_sync_from_add_list(&tmp_add_list, list); + all_added = hclge_sync_from_add_list(&tmp_add_list, list);
spin_unlock_bh(&vport->mac_list_lock); + + hclge_update_overflow_flags(vport, mac_type, all_added); + return;
clear_tmp_list: @@ -7864,7 +7888,7 @@ static bool hclge_need_sync_mac_table(struct hclge_vport *vport) struct hclge_dev *hdev = vport->back; bool time_up;
- if (test_bit(HCLGE_VPORT_STATE_BLOCK_CONFIG, &vport->state)) + if (test_bit(vport->vport_id, hdev->vport_config_block)) return false;
time_up = !(hdev->serv_processed_cnt % HCLGE_MAC_TBL_SYNC_INTERVAL); @@ -7896,7 +7920,8 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, { int (*unsync)(struct hclge_vport *vport, const unsigned char *addr); struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp; - struct list_head *list; + struct hclge_dev *hdev = vport->back; + struct list_head tmp_del_list, *list; int ret;
if (mac_type == HCLGE_MAC_ADDR_UC) { @@ -7907,18 +7932,33 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, unsync = hclge_rm_mc_addr_common; }
+ INIT_LIST_HEAD(&tmp_del_list); + if (!is_del_list) - set_bit(HCLGE_VPORT_STATE_BLOCK_CONFIG, &vport->state); + set_bit(vport->vport_id, hdev->vport_config_block); + + spin_lock_bh(&vport->mac_list_lock);
list_for_each_entry_safe(mac_cfg, tmp, list, node) { - if (mac_cfg->state == HCLGE_MAC_TO_ADD) { + switch (mac_cfg->state) { + case HCLGE_MAC_TO_DEL: + case HCLGE_MAC_DEL_FAIL: + case HCLGE_MAC_ACTIVE: + list_del(&mac_cfg->node); + list_add_tail(&mac_cfg->node, &tmp_del_list); + break; + case HCLGE_MAC_TO_ADD: if (is_del_list) { list_del(&mac_cfg->node); kfree(mac_cfg); } - continue; + break; } + }
+ spin_unlock_bh(&vport->mac_list_lock); + + list_for_each_entry_safe(mac_cfg, tmp, &tmp_del_list, node) { ret = unsync(vport, mac_cfg->mac_addr); if (!ret || ret == -ENOENT) { /* clear all mac addr from hardware, but remain these @@ -7936,6 +7976,12 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, mac_cfg->state = HCLGE_MAC_TO_DEL; } } + + spin_lock_bh(&vport->mac_list_lock); + + hclge_sync_from_del_list(&tmp_del_list, list); + + spin_unlock_bh(&vport->mac_list_lock); }
/* remove all mac address when uninitailize */ @@ -8240,10 +8286,13 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p, /* if old dev addr restore failed, add to the uc mac list, * and try to restore it in service task */ - if (old_mac_removed) + if (old_mac_removed) { + spin_lock_bh(&vport->mac_list_lock); hclge_modify_mac_node_state(&vport->uc_mac_list, hdev->hw.mac.mac_addr, HCLGE_MAC_TO_ADD); + spin_unlock_bh(&vport->mac_list_lock); + }
return -EIO; } @@ -8893,19 +8942,10 @@ static void hclge_mac_node_convert_for_reset(struct list_head *list)
void hclge_restore_mac_table_common(struct hclge_vport *vport) { - hclge_mac_node_convert_for_reset(&vport->uc_mac_list); - hclge_mac_node_convert_for_reset(&vport->mc_mac_list); - clear_bit(HCLGE_VPORT_STATE_BLOCK_CONFIG, &vport->state); -} - -static void hclge_restore_pf_mac_table(struct hclge_vport *vport) -{ - /* move the mac addr to the tmp_add_list and tmp_del_list, then - * we can add/delete these mac addr outside the spin lock - */ spin_lock_bh(&vport->mac_list_lock);
- hclge_restore_mac_table_common(vport); + hclge_mac_node_convert_for_reset(&vport->uc_mac_list); + hclge_mac_node_convert_for_reset(&vport->mc_mac_list);
spin_unlock_bh(&vport->mac_list_lock); } @@ -8915,10 +8955,9 @@ static int hclge_restore_hw_table(struct hclge_dev *hdev) struct hclge_vport *vport = &hdev->vport[0]; struct hnae3_handle *handle = &vport->nic;
- bitmap_set(hdev->need_restore_vf_table, 0, hdev->num_alloc_vport); - - hclge_restore_pf_mac_table(vport); + hclge_restore_mac_table_common(vport); hclge_restore_vport_vlan_table(vport); + set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state);
return hclge_restore_fd_entries(handle); } @@ -10299,6 +10338,8 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) hdev->reset_type == HNAE3_GLOBAL_RESET) { memset(hdev->vlan_table, 0, sizeof(hdev->vlan_table)); memset(hdev->vf_vlan_full, 0, sizeof(hdev->vf_vlan_full)); + bitmap_set(hdev->vport_config_block, 0, hdev->num_alloc_vport); + hclge_reset_umv_space(hdev); }
ret = hclge_cmd_init(hdev); @@ -10313,8 +10354,6 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; }
- hclge_reset_umv_space(hdev); - ret = hclge_mac_init(hdev); if (ret) { dev_err(&pdev->dev, "Mac init error, ret = %d\n", ret); @@ -11126,6 +11165,30 @@ static void hclge_reset_vf_rate(struct hclge_dev *hdev) } }
+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; + int ret; + + if (vport->last_promisc_flags != vport->overflow_promisc_flags) { + set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); + vport->last_promisc_flags = vport->overflow_promisc_flags; + } + + if (test_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state)) { + 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_STATE_PROMISC_CHANGED, &hdev->state); + hclge_enable_vlan_filter(handle, + tmp_flags & HNAE3_VLAN_FLTR); + } + } +} + struct hnae3_ae_ops hclge_ops = { .init_ae_dev = hclge_init_ae_dev, .uninit_ae_dev = hclge_uninit_ae_dev, @@ -11138,6 +11201,7 @@ struct hnae3_ae_ops hclge_ops = { .get_vector = hclge_get_vector, .put_vector = hclge_put_vector, .set_promisc_mode = hclge_set_promisc_mode, + .request_update_promisc_mode = hclge_request_update_promisc_mode, .set_loopback = hclge_set_loopback, .start = hclge_ae_start, .stop = hclge_ae_stop, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 05ab6c1..0040d6d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -221,6 +221,7 @@ enum HCLGE_DEV_STATE { HCLGE_STATE_STATISTICS_UPDATING, HCLGE_STATE_CMD_DISABLE, HCLGE_STATE_LINK_UPDATING, + HCLGE_STATE_PROMISC_CHANGED, HCLGE_STATE_MAX };
@@ -814,7 +815,7 @@ struct hclge_dev { unsigned long vlan_table[VLAN_N_VID][BITS_TO_LONGS(HCLGE_VPORT_NUM)]; unsigned long vf_vlan_full[BITS_TO_LONGS(HCLGE_VPORT_NUM)];
- unsigned long need_restore_vf_table[BITS_TO_LONGS(HCLGE_VPORT_NUM)]; + unsigned long vport_config_block[BITS_TO_LONGS(HCLGE_VPORT_NUM)];
struct hclge_fd_cfg fd_cfg; struct hlist_head fd_rule_list; @@ -879,7 +880,6 @@ struct hclge_rss_tuple_cfg { enum HCLGE_VPORT_STATE { HCLGE_VPORT_STATE_ALIVE, HCLGE_VPORT_STATE_MAC_TBL_CHANGE, - HCLGE_VPORT_STATE_BLOCK_CONFIG, /* blocking mac configuration */ HCLGE_VPORT_STATE_MAX };
@@ -944,6 +944,8 @@ struct hclge_vport { u32 max_tx_rate; u32 trusted; u16 promisc_enable; + u8 overflow_promisc_flags; + u8 last_promisc_flags;
spinlock_t mac_list_lock; /* protect mac address need to add/detele */ struct list_head uc_mac_list; /* Store VF unicast table */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index e93e8d7..7636411 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -276,14 +276,19 @@ static int hclge_modify_vf_mac_addr(struct hclge_vport *vport, ret = hclge_add_uc_addr_common(vport, new_addr); if (ret) { ret = hclge_add_uc_addr_common(vport, old_addr); - if (ret) + if (ret) { + spin_lock_bh(&vport->mac_list_lock); hclge_modify_mac_node_state(&vport->uc_mac_list, old_addr, HCLGE_MAC_TO_ADD); + spin_unlock_bh(&vport->mac_list_lock); + } return -EIO;
} else { + spin_lock_bh(&vport->mac_list_lock); hclge_replace_mac_node(&vport->uc_mac_list, old_addr, new_addr, !old_mac_removed); + spin_unlock_bh(&vport->mac_list_lock); } return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index c52b070..aa6541e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1160,6 +1160,27 @@ static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc, en_bc_pmc); }
+static void hclgevf_request_update_promisc_mode(struct hnae3_handle *handle) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + + set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state); +} + +static void hclgevf_sync_promisc_mode(struct hclgevf_dev *hdev) +{ + struct hnae3_handle *handle = &hdev->nic; + bool en_uc_pmc = handle->netdev_flags & HNAE3_UPE; + bool en_mc_pmc = handle->netdev_flags & HNAE3_MPE; + int ret; + + if (test_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state)) { + ret = hclgevf_set_promisc_mode(handle, en_uc_pmc, en_mc_pmc); + if (!ret) + clear_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state); + } +} + static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, unsigned int tqp_id, int stream_id, bool enable) { @@ -2116,6 +2137,8 @@ static void hclgevf_periodical_service_task(struct hclgevf_dev *hdev)
hclgevf_sync_mac_table(hdev);
+ hclgevf_sync_promisc_mode(hdev); + hdev->last_serv_processed = jiffies;
out: @@ -2914,6 +2937,8 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) return ret; }
+ set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state); + dev_info(&hdev->pdev->dev, "Reset done\n");
return 0; @@ -3420,6 +3445,7 @@ void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, .set_timer_task = hclgevf_set_timer_task, .get_link_mode = hclgevf_get_link_mode, .set_promisc_mode = hclgevf_set_promisc_mode, + .request_update_promisc_mode = hclgevf_request_update_promisc_mode, };
static struct hnae3_ae_algo ae_algovf = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index cb62472..2d30c61 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -150,6 +150,7 @@ enum hclgevf_states { HCLGEVF_STATE_MBX_HANDLING, HCLGEVF_STATE_CMD_DISABLE, HCLGEVF_STATE_LINK_UPDATING, + HCLGEVF_STATE_PROMISC_CHANGED, };
#define HCLGEVF_MPF_ENBALE 1