From: Jian Shen shenjian15@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
Currently, there is a time window for protect share_umv_size between checking umv space and doing mac configuration in the lin function hclge_add_uc_addr_common(). It should be extented.
On the other hand, for the mac address configuration is not configured directly in the path of hns3_set_rx_mode any more, so it's unnecessary to use spin lock to protect the share_umv_size. Another exist mutex vport_lock is designed to protect the share resource between each vport can replace it.
This patch uses mutex vport_lock intead of spin lock umv_lock to protect share_umv_size, and adjusts the mutex region.
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 --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 32 ++++++++++++++-------- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 - 2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c75e24e..24c6498 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7301,7 +7301,6 @@ static int hclge_init_umv_space(struct hclge_dev *hdev) "Alloc umv space failed, want %u, get %u\n", hdev->wanted_umv_size, allocated_size);
- spin_lock_init(&hdev->umv_lock); hdev->max_umv_size = allocated_size; hdev->priv_umv_size = hdev->max_umv_size / (hdev->num_alloc_vport + 1); hdev->share_umv_size = hdev->priv_umv_size + @@ -7320,21 +7319,25 @@ static void hclge_reset_umv_space(struct hclge_dev *hdev) vport->used_umv_num = 0; }
- spin_lock(&hdev->umv_lock); + mutex_lock(&hdev->vport_lock); hdev->share_umv_size = hdev->priv_umv_size + hdev->max_umv_size % (hdev->num_alloc_vport + 1); - spin_unlock(&hdev->umv_lock); + mutex_unlock(&hdev->vport_lock); }
-static bool hclge_is_umv_space_full(struct hclge_vport *vport) +static bool hclge_is_umv_space_full(struct hclge_vport *vport, bool need_lock) { struct hclge_dev *hdev = vport->back; bool is_full;
- spin_lock(&hdev->umv_lock); + if (need_lock) + mutex_lock(&hdev->vport_lock); + is_full = (vport->used_umv_num >= hdev->priv_umv_size && hdev->share_umv_size == 0); - spin_unlock(&hdev->umv_lock); + + if (need_lock) + mutex_unlock(&hdev->vport_lock);
return is_full; } @@ -7343,7 +7346,6 @@ static void hclge_update_umv_space(struct hclge_vport *vport, bool is_free) { struct hclge_dev *hdev = vport->back;
- spin_lock(&hdev->umv_lock); if (is_free) { if (vport->used_umv_num > hdev->priv_umv_size) hdev->share_umv_size++; @@ -7356,7 +7358,6 @@ static void hclge_update_umv_space(struct hclge_vport *vport, bool is_free) hdev->share_umv_size--; vport->used_umv_num++; } - spin_unlock(&hdev->umv_lock); }
static struct hclge_vport_mac_addr_cfg * @@ -7497,12 +7498,16 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport, */ ret = hclge_lookup_mac_vlan_tbl(vport, &req, &desc, false); if (ret == -ENOENT) { - if (!hclge_is_umv_space_full(vport)) { + mutex_lock(&hdev->vport_lock); + if (!hclge_is_umv_space_full(vport, false)) { ret = hclge_add_mac_vlan_tbl(vport, &req, NULL); if (!ret) hclge_update_umv_space(vport, false); + + mutex_unlock(&hdev->vport_lock); return ret; } + mutex_unlock(&hdev->vport_lock);
dev_err(&hdev->pdev->dev, "UC MAC table full(%u)\n", hdev->priv_umv_size); @@ -7558,10 +7563,13 @@ int hclge_rm_uc_addr_common(struct hclge_vport *vport, hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0); hclge_prepare_mac_addr(&req, addr, false); ret = hclge_remove_mac_vlan_tbl(vport, &req); - if (!ret) + if (!ret) { + mutex_lock(&hdev->vport_lock); hclge_update_umv_space(vport, true); - else if (ret == -ENOENT) + mutex_unlock(&hdev->vport_lock); + } else if (ret == -ENOENT) { ret = 0; + }
return ret; } @@ -10207,7 +10215,7 @@ static int hclge_set_vf_spoofchk(struct hnae3_handle *handle, int vf, dev_warn(&hdev->pdev->dev, "vf %d vlan table is full, enable spoof check may cause its packet send fail\n", vf); - else if (enable && hclge_is_umv_space_full(vport)) + else if (enable && hclge_is_umv_space_full(vport, true)) dev_warn(&hdev->pdev->dev, "vf %d mac table is full, enable spoof check may cause its packet send fail\n", vf); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index cfb9ba2..68ea032 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -832,7 +832,6 @@ struct hclge_dev { u16 priv_umv_size; /* unicast mac vlan space shared by PF and its VFs */ u16 share_umv_size; - spinlock_t umv_lock; /* protect share_umv_size */
DECLARE_KFIFO(mac_tnl_log, struct hclge_mac_tnl_stats, HCLGE_MAC_TNL_LOG_SIZE);