| From 580ff2dc75565693e096f63ae2e0262f926c212b Mon Sep 17 00:00:00 2001 |
| From: Jian Shen <shenjian15@huawei.com> |
| Date: Thu, 4 Apr 2019 16:17:55 +0800 |
| Subject: net: hns3: add protect when handling mac addr list |
| |
| [ Upstream commit 389775a6605e040dddea21a778a88eaaa57c068d ] |
| |
| It used netdev->uc and netdev->mc list in function |
| hns3_recover_hw_addr() and hns3_remove_hw_addr(). |
| We should add protect for them. |
| |
| Fixes: f05e21097121 ("net: hns3: Clear mac vlan table entries when unload driver or function reset") |
| Signed-off-by: Jian Shen <shenjian15@huawei.com> |
| Signed-off-by: Peng Li <lipeng321@huawei.com> |
| Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 10 ++++++++-- |
| 1 file changed, 8 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c |
| index d6b488c2de332..c7d310903319f 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c |
| @@ -3774,12 +3774,13 @@ static int hns3_recover_hw_addr(struct net_device *ndev) |
| struct netdev_hw_addr *ha, *tmp; |
| int ret = 0; |
| |
| + netif_addr_lock_bh(ndev); |
| /* go through and sync uc_addr entries to the device */ |
| list = &ndev->uc; |
| list_for_each_entry_safe(ha, tmp, &list->list, list) { |
| ret = hns3_nic_uc_sync(ndev, ha->addr); |
| if (ret) |
| - return ret; |
| + goto out; |
| } |
| |
| /* go through and sync mc_addr entries to the device */ |
| @@ -3787,9 +3788,11 @@ static int hns3_recover_hw_addr(struct net_device *ndev) |
| list_for_each_entry_safe(ha, tmp, &list->list, list) { |
| ret = hns3_nic_mc_sync(ndev, ha->addr); |
| if (ret) |
| - return ret; |
| + goto out; |
| } |
| |
| +out: |
| + netif_addr_unlock_bh(ndev); |
| return ret; |
| } |
| |
| @@ -3800,6 +3803,7 @@ static void hns3_remove_hw_addr(struct net_device *netdev) |
| |
| hns3_nic_uc_unsync(netdev, netdev->dev_addr); |
| |
| + netif_addr_lock_bh(netdev); |
| /* go through and unsync uc_addr entries to the device */ |
| list = &netdev->uc; |
| list_for_each_entry_safe(ha, tmp, &list->list, list) |
| @@ -3810,6 +3814,8 @@ static void hns3_remove_hw_addr(struct net_device *netdev) |
| list_for_each_entry_safe(ha, tmp, &list->list, list) |
| if (ha->refcount > 1) |
| hns3_nic_mc_unsync(netdev, ha->addr); |
| + |
| + netif_addr_unlock_bh(netdev); |
| } |
| |
| static void hns3_clear_tx_ring(struct hns3_enet_ring *ring) |
| -- |
| 2.20.1 |
| |