]> err.no Git - linux-2.6/blobdiff - net/core/dev_mcast.c
[NET] CORE: Fix whitespace errors.
[linux-2.6] / net / core / dev_mcast.c
index 5cc9b448c44300bc3b77629039884cb846815230..99aece1aeccff9aa950c3b8bb08385b8dd2b2b25 100644 (file)
@@ -72,10 +72,9 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
        int err;
 
        netif_tx_lock_bh(dev);
-       err = __dev_addr_delete(&dev->mc_list, addr, alen, glbl);
+       err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
+                               addr, alen, glbl);
        if (!err) {
-               dev->mc_count--;
-
                /*
                 *      We have altered the list, so the card
                 *      loaded filter is now wrong. Fix it
@@ -96,26 +95,87 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
        int err;
 
        netif_tx_lock_bh(dev);
-       err = __dev_addr_add(&dev->mc_list, addr, alen, glbl);
-       if (!err) {
-               dev->mc_count++;
+       err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
+       if (!err)
                __dev_set_rx_mode(dev);
-       }
        netif_tx_unlock_bh(dev);
        return err;
 }
 
-/*
- *     Discard multicast list when a device is downed
+/**
+ *     dev_mc_sync     - Synchronize device's multicast list to another device
+ *     @to: destination device
+ *     @from: source device
+ *
+ *     Add newly added addresses to the destination device and release
+ *     addresses that have no users left. The source device must be
+ *     locked by netif_tx_lock_bh.
+ *
+ *     This function is intended to be called from the dev->set_multicast_list
+ *     function of layered software devices.
  */
+int dev_mc_sync(struct net_device *to, struct net_device *from)
+{
+       struct dev_addr_list *da;
+       int err = 0;
+
+       netif_tx_lock_bh(to);
+       for (da = from->mc_list; da != NULL; da = da->next) {
+               if (!da->da_synced) {
+                       err = __dev_addr_add(&to->mc_list, &to->mc_count,
+                                            da->da_addr, da->da_addrlen, 0);
+                       if (err < 0)
+                               break;
+                       da->da_synced = 1;
+                       da->da_users++;
+               } else if (da->da_users == 1) {
+                       __dev_addr_delete(&to->mc_list, &to->mc_count,
+                                         da->da_addr, da->da_addrlen, 0);
+                       __dev_addr_delete(&from->mc_list, &from->mc_count,
+                                         da->da_addr, da->da_addrlen, 0);
+               }
+       }
+       if (!err)
+               __dev_set_rx_mode(to);
+       netif_tx_unlock_bh(to);
+
+       return err;
+}
+EXPORT_SYMBOL(dev_mc_sync);
+
 
-void dev_mc_discard(struct net_device *dev)
+/**
+ *     dev_mc_unsync   - Remove synchronized addresses from the destination
+ *                       device
+ *     @to: destination device
+ *     @from: source device
+ *
+ *     Remove all addresses that were added to the destination device by
+ *     dev_mc_sync(). This function is intended to be called from the
+ *     dev->stop function of layered software devices.
+ */
+void dev_mc_unsync(struct net_device *to, struct net_device *from)
 {
-       netif_tx_lock_bh(dev);
-       __dev_addr_discard(&dev->mc_list);
-       dev->mc_count = 0;
-       netif_tx_unlock_bh(dev);
+       struct dev_addr_list *da;
+
+       netif_tx_lock_bh(from);
+       netif_tx_lock_bh(to);
+
+       for (da = from->mc_list; da != NULL; da = da->next) {
+               if (!da->da_synced)
+                       continue;
+               __dev_addr_delete(&to->mc_list, &to->mc_count,
+                                 da->da_addr, da->da_addrlen, 0);
+               da->da_synced = 0;
+               __dev_addr_delete(&from->mc_list, &from->mc_count,
+                                 da->da_addr, da->da_addrlen, 0);
+       }
+       __dev_set_rx_mode(to);
+
+       netif_tx_unlock_bh(to);
+       netif_tx_unlock_bh(from);
 }
+EXPORT_SYMBOL(dev_mc_unsync);
 
 #ifdef CONFIG_PROC_FS
 static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)