Implement the ndo_set_rx_mode_async callback and update
the driver to use the snapshot/commit model for RX mode update.

Signed-off-by: I Viswanath <[email protected]>
---
 
Call paths involving netif_set_rx_mode in vmxnet3

netif_set_rx_mode
`-- vmxnet3_activate_dev
    |-- vmxnet3_open (ndo_open, takes lock)
    |-- vmxnet3_change_mtu (ndo_change_mtu, takes lock)
    |-- vmxnet3_reset_work (takes lock)
    |-- vmxnet3_resume (lock added)
    |-- vmxnet3_set_ringparam (ethtool callback, takes lock)
    `-- vmxnet3_xdp_set
        `-- vmxnet3_xdp (ndo_bpf, takes lock)

 drivers/net/vmxnet3/vmxnet3_drv.c | 46 +++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 11 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c 
b/drivers/net/vmxnet3/vmxnet3_drv.c
index 40522afc0532..350e44286c00 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2775,18 +2775,18 @@ static u8 *
 vmxnet3_copy_mc(struct net_device *netdev)
 {
        u8 *buf = NULL;
-       u32 sz = netdev_mc_count(netdev) * ETH_ALEN;
+       u32 sz = netif_rx_mode_mc_count(netdev) * ETH_ALEN;
+       char *ha_addr;
+       int ni;
 
        /* struct Vmxnet3_RxFilterConf.mfTableLen is u16. */
        if (sz <= 0xffff) {
                /* We may be called with BH disabled */
                buf = kmalloc(sz, GFP_ATOMIC);
                if (buf) {
-                       struct netdev_hw_addr *ha;
                        int i = 0;
-
-                       netdev_for_each_mc_addr(ha, netdev)
-                               memcpy(buf + i++ * ETH_ALEN, ha->addr,
+                       netif_rx_mode_for_each_mc_addr(ha_addr, netdev, ni)
+                               memcpy(buf + i++ * ETH_ALEN, ha_addr,
                                       ETH_ALEN);
                }
        }
@@ -2796,8 +2796,23 @@ vmxnet3_copy_mc(struct net_device *netdev)
 
 static void
 vmxnet3_set_mc(struct net_device *netdev)
+{
+       bool allmulti = !!(netdev->flags & IFF_ALLMULTI);
+       bool promisc = !!(netdev->flags & IFF_PROMISC);
+       bool broadcast = !!(netdev->flags & IFF_BROADCAST);
+
+       netif_set_rx_mode_flag(netdev, NETIF_RX_MODE_UC_SKIP, true);
+       netif_set_rx_mode_flag(netdev, NETIF_RX_MODE_MC_SKIP, allmulti);
+
+       netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_ALLMULTI, allmulti);
+       netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC, promisc);
+       netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_BROADCAST, broadcast);
+}
+
+static void vmxnet3_set_mc_async(struct net_device *netdev)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       int mc_count = netif_rx_mode_mc_count(netdev);
        unsigned long flags;
        struct Vmxnet3_RxFilterConf *rxConf =
                                        &adapter->shared->devRead.rxFilterConf;
@@ -2806,7 +2821,7 @@ vmxnet3_set_mc(struct net_device *netdev)
        bool new_table_pa_valid = false;
        u32 new_mode = VMXNET3_RXM_UCAST;
 
-       if (netdev->flags & IFF_PROMISC) {
+       if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC)) {
                u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
                memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable));
 
@@ -2815,16 +2830,16 @@ vmxnet3_set_mc(struct net_device *netdev)
                vmxnet3_restore_vlan(adapter);
        }
 
-       if (netdev->flags & IFF_BROADCAST)
+       if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_BROADCAST))
                new_mode |= VMXNET3_RXM_BCAST;
 
-       if (netdev->flags & IFF_ALLMULTI)
+       if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_ALLMULTI))
                new_mode |= VMXNET3_RXM_ALL_MULTI;
        else
-               if (!netdev_mc_empty(netdev)) {
+               if (mc_count) {
                        new_table = vmxnet3_copy_mc(netdev);
                        if (new_table) {
-                               size_t sz = netdev_mc_count(netdev) * ETH_ALEN;
+                               size_t sz = mc_count * ETH_ALEN;
 
                                rxConf->mfTableLen = cpu_to_le16(sz);
                                new_table_pa = dma_map_single(
@@ -3213,7 +3228,7 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
        }
 
        /* Apply the rx filter settins last. */
-       vmxnet3_set_mc(adapter->netdev);
+       netif_set_rx_mode(adapter->netdev);
 
        /*
         * Check link state when first activating device. It will start the
@@ -3977,6 +3992,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
                .ndo_get_stats64 = vmxnet3_get_stats64,
                .ndo_tx_timeout = vmxnet3_tx_timeout,
                .ndo_set_rx_mode = vmxnet3_set_mc,
+               .ndo_set_rx_mode_async = vmxnet3_set_mc_async,
                .ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
                .ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -4400,6 +4416,7 @@ static void vmxnet3_shutdown_device(struct pci_dev *pdev)
        vmxnet3_disable_all_intrs(adapter);
 
        clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+       netif_disable_async_ops(netdev);
 }
 
 
@@ -4518,6 +4535,7 @@ vmxnet3_suspend(struct device *device)
        pci_disable_device(pdev);
        pci_set_power_state(pdev, pci_choose_state(pdev, PMSG_SUSPEND));
 
+       netif_disable_async_ops(netdev);
        return 0;
 }
 
@@ -4531,6 +4549,8 @@ vmxnet3_resume(struct device *device)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
+       netif_enable_async_ops(netdev);
+
        if (!netif_running(netdev))
                return 0;
 
@@ -4559,7 +4579,11 @@ vmxnet3_resume(struct device *device)
        vmxnet3_rq_cleanup_all(adapter);
 
        vmxnet3_reset_dev(adapter);
+
+       rtnl_lock();
        err = vmxnet3_activate_dev(adapter);
+       rtnl_unlock();
+
        if (err != 0) {
                netdev_err(netdev,
                           "failed to re-activate on resume, error: %d", err);
-- 
2.47.3


Reply via email to