static void hns3_clear_all_ring(struct hnae3_handle *h);
 static void hns3_force_clear_all_rx_ring(struct hnae3_handle *h);
+static void hns3_remove_hw_addr(struct net_device *netdev);
 
 static const char hns3_driver_name[] = "hns3";
 const char hns3_driver_version[] = VERMAGIC_STRING;
 
 }
 
-static void hns3_uninit_mac_addr(struct net_device *netdev)
-{
-       struct hns3_nic_priv *priv = netdev_priv(netdev);
-       struct hnae3_handle *h = priv->ae_handle;
-
-       if (h->ae_algo->ops->rm_uc_addr)
-               h->ae_algo->ops->rm_uc_addr(h, netdev->dev_addr);
-}
-
 static int hns3_restore_fd_rules(struct net_device *netdev)
 {
        struct hnae3_handle *h = hns3_get_handle(netdev);
        struct hns3_nic_priv *priv = netdev_priv(netdev);
        int ret;
 
+       hns3_remove_hw_addr(netdev);
+
        if (netdev->reg_state != NETREG_UNINITIALIZED)
                unregister_netdev(netdev);
 
 
        priv->ring_data = NULL;
 
-       hns3_uninit_mac_addr(netdev);
-
        free_netdev(netdev);
 }
 
                hns3_nic_mc_sync(ndev, ha->addr);
 }
 
+static void hns3_remove_hw_addr(struct net_device *netdev)
+{
+       struct netdev_hw_addr_list *list;
+       struct netdev_hw_addr *ha, *tmp;
+
+       hns3_nic_uc_unsync(netdev, netdev->dev_addr);
+
+       /* go through and unsync uc_addr entries to the device */
+       list = &netdev->uc;
+       list_for_each_entry_safe(ha, tmp, &list->list, list)
+               hns3_nic_uc_unsync(netdev, ha->addr);
+
+       /* go through and unsync mc_addr entries to the device */
+       list = &netdev->mc;
+       list_for_each_entry_safe(ha, tmp, &list->list, list)
+               if (ha->refcount > 1)
+                       hns3_nic_mc_unsync(netdev, ha->addr);
+}
+
 static void hns3_clear_tx_ring(struct hns3_enet_ring *ring)
 {
        while (ring->next_to_clean != ring->next_to_use) {
        if (ret)
                netdev_err(netdev, "uninit ring error\n");
 
-       hns3_uninit_mac_addr(netdev);
-
-       /* it is cumbersome for hardware to pick-and-choose rules for deletion
-        * from TCAM. Hence, for function reset software intervention is
-        * required to delete the rules
+       /* it is cumbersome for hardware to pick-and-choose entries for deletion
+        * from table space. Hence, for function reset software intervention is
+        * required to delete the entries
         */
-       if (hns3_dev_ongoing_func_reset(ae_dev))
+       if (hns3_dev_ongoing_func_reset(ae_dev)) {
+               hns3_remove_hw_addr(netdev);
                hns3_del_all_fd_rules(netdev, false);
+       }
 
        return ret;
 }