]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/dev_mcast.c
[RTNETLINK]: rtnl_link: allow specifying initial device address
[linux-2.6-omap-h63xx.git] / net / core / dev_mcast.c
index 7d57bf77f3a3d186a0000c87c8a7329eb56a3f64..aa38100601fb31d2c6d73e83ddb30f62d884c45a 100644 (file)
  *     We block accesses to device mc filters with netif_tx_lock.
  */
 
-/*
- *     Update the multicast list into the physical NIC controller.
- */
-
-static void __dev_mc_upload(struct net_device *dev)
-{
-       /* Don't do anything till we up the interface
-        * [dev_open will call this function so the list will
-        * stay sane]
-        */
-
-       if (!(dev->flags&IFF_UP))
-               return;
-
-       /*
-        *      Devices with no set multicast or which have been
-        *      detached don't get set.
-        */
-
-       if (dev->set_multicast_list == NULL ||
-           !netif_device_present(dev))
-               return;
-
-       dev->set_multicast_list(dev);
-}
-
-void dev_mc_upload(struct net_device *dev)
-{
-       netif_tx_lock_bh(dev);
-       __dev_mc_upload(dev);
-       netif_tx_unlock_bh(dev);
-}
-
 /*
  *     Delete a device level multicast
  */
 
 int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
 {
-       int err = 0;
-       struct dev_mc_list *dmi, **dmip;
+       int err;
 
        netif_tx_lock_bh(dev);
-
-       for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
+       err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
+                               addr, alen, glbl);
+       if (!err) {
                /*
-                *      Find the entry we want to delete. The device could
-                *      have variable length entries so check these too.
+                *      We have altered the list, so the card
+                *      loaded filter is now wrong. Fix it
                 */
-               if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
-                   alen == dmi->dmi_addrlen) {
-                       if (glbl) {
-                               int old_glbl = dmi->dmi_gusers;
-                               dmi->dmi_gusers = 0;
-                               if (old_glbl == 0)
-                                       break;
-                       }
-                       if (--dmi->dmi_users)
-                               goto done;
 
-                       /*
-                        *      Last user. So delete the entry.
-                        */
-                       *dmip = dmi->next;
-                       dev->mc_count--;
-
-                       kfree(dmi);
-
-                       /*
-                        *      We have altered the list, so the card
-                        *      loaded filter is now wrong. Fix it
-                        */
-                       __dev_mc_upload(dev);
-
-                       netif_tx_unlock_bh(dev);
-                       return 0;
-               }
+               __dev_set_rx_mode(dev);
        }
-       err = -ENOENT;
-done:
        netif_tx_unlock_bh(dev);
        return err;
 }
@@ -153,46 +92,13 @@ done:
 
 int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 {
-       int err = 0;
-       struct dev_mc_list *dmi, *dmi1;
-
-       dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
+       int err;
 
        netif_tx_lock_bh(dev);
-       for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
-               if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
-                   dmi->dmi_addrlen == alen) {
-                       if (glbl) {
-                               int old_glbl = dmi->dmi_gusers;
-                               dmi->dmi_gusers = 1;
-                               if (old_glbl)
-                                       goto done;
-                       }
-                       dmi->dmi_users++;
-                       goto done;
-               }
-       }
-
-       if ((dmi = dmi1) == NULL) {
-               netif_tx_unlock_bh(dev);
-               return -ENOMEM;
-       }
-       memcpy(dmi->dmi_addr, addr, alen);
-       dmi->dmi_addrlen = alen;
-       dmi->next = dev->mc_list;
-       dmi->dmi_users = 1;
-       dmi->dmi_gusers = glbl ? 1 : 0;
-       dev->mc_list = dmi;
-       dev->mc_count++;
-
-       __dev_mc_upload(dev);
-
-       netif_tx_unlock_bh(dev);
-       return 0;
-
-done:
+       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);
-       kfree(dmi1);
        return err;
 }
 
@@ -203,16 +109,8 @@ done:
 void dev_mc_discard(struct net_device *dev)
 {
        netif_tx_lock_bh(dev);
-
-       while (dev->mc_list != NULL) {
-               struct dev_mc_list *tmp = dev->mc_list;
-               dev->mc_list = tmp->next;
-               if (tmp->dmi_users > tmp->dmi_gusers)
-                       printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users);
-               kfree(tmp);
-       }
+       __dev_addr_discard(&dev->mc_list);
        dev->mc_count = 0;
-
        netif_tx_unlock_bh(dev);
 }
 
@@ -223,7 +121,7 @@ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
        loff_t off = 0;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                if (off++ == *pos)
                        return dev;
        }
@@ -232,9 +130,8 @@ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
 
 static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       struct net_device *dev = v;
        ++*pos;
-       return dev->next;
+       return next_net_device((struct net_device *)v);
 }
 
 static void dev_mc_seq_stop(struct seq_file *seq, void *v)
@@ -245,7 +142,7 @@ static void dev_mc_seq_stop(struct seq_file *seq, void *v)
 
 static int dev_mc_seq_show(struct seq_file *seq, void *v)
 {
-       struct dev_mc_list *m;
+       struct dev_addr_list *m;
        struct net_device *dev = v;
 
        netif_tx_lock_bh(dev);
@@ -293,4 +190,3 @@ void __init dev_mcast_init(void)
 
 EXPORT_SYMBOL(dev_mc_add);
 EXPORT_SYMBOL(dev_mc_delete);
-EXPORT_SYMBOL(dev_mc_upload);