commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 04/26: commit ccffad25b5136958d4769ed6de5e87992dd9c65c


From: Samuel Thibault
Subject: [hurd] 04/26: commit ccffad25b5136958d4769ed6de5e87992dd9c65c
Date: Tue, 22 Sep 2015 21:51:47 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch dde
in repository hurd.

commit d1fbd2c1aa074259fd1bfda9774364f82a4a77ac
Author: Jiri Pirko <address@hidden>
Date:   Fri May 22 23:22:17 2009 +0000

    commit ccffad25b5136958d4769ed6de5e87992dd9c65c
    
        net: convert unicast addr list
    
        This patch converts unicast address list to standard list_head using
        previously introduced struct netdev_hw_addr. It also relaxes the
        locking. Original spinlock (still used for multicast addresses) is not
        needed and is no longer used for a protection of this list. All
        reading and writing takes place under rtnl (with no changes).
    
        I also removed a possibility to specify the length of the address
        while adding or deleting unicast address. It's always dev->addr_len.
    
        The convertion touched especially e1000 and ixgbe codes when the
        change is not so trivial.
    
        Signed-off-by: Jiri Pirko <address@hidden>
    
         drivers/net/bnx2.c               |   13 +--
         drivers/net/e1000/e1000_main.c   |   24 +++--
         drivers/net/ixgbe/ixgbe_common.c |   14 ++--
         drivers/net/ixgbe/ixgbe_common.h |    4 +-
         drivers/net/ixgbe/ixgbe_main.c   |    6 +-
         drivers/net/ixgbe/ixgbe_type.h   |    4 +-
         drivers/net/macvlan.c            |   11 +-
         drivers/net/mv643xx_eth.c        |   11 +-
         drivers/net/niu.c                |    7 +-
         drivers/net/virtio_net.c         |    7 +-
         drivers/s390/net/qeth_l2_main.c  |    6 +-
         drivers/scsi/fcoe/fcoe.c         |   16 ++--
         include/linux/netdevice.h        |   18 ++--
         net/8021q/vlan.c                 |    4 +-
         net/8021q/vlan_dev.c             |   10 +-
         net/core/dev.c                   |  195 
+++++++++++++++++++++++++++-----------
         net/dsa/slave.c                  |   10 +-
         net/packet/af_packet.c           |    4 +-
         18 files changed, 227 insertions(+), 137 deletions(-)
        Signed-off-by: David S. Miller <address@hidden>
---
 libdde_linux26/contrib/include/linux/netdevice.h |  18 ++-
 libdde_linux26/lib/src/net/core/dev.c            | 195 ++++++++++++++++-------
 2 files changed, 149 insertions(+), 64 deletions(-)

diff --git a/libdde_linux26/contrib/include/linux/netdevice.h 
b/libdde_linux26/contrib/include/linux/netdevice.h
index 3f2cd12..d85de86 100644
--- a/libdde_linux26/contrib/include/linux/netdevice.h
+++ b/libdde_linux26/contrib/include/linux/netdevice.h
@@ -215,9 +215,12 @@ struct netdev_hw_addr {
        struct list_head        list;
        unsigned char           addr[MAX_ADDR_LEN];
        unsigned char           type;
-#define NETDEV_HW_ADDR_T_LAN   1
-#define NETDEV_HW_ADDR_T_SAN   2
-#define NETDEV_HW_ADDR_T_SLAVE 3
+#define NETDEV_HW_ADDR_T_LAN           1
+#define NETDEV_HW_ADDR_T_SAN           2
+#define NETDEV_HW_ADDR_T_SLAVE         3
+#define NETDEV_HW_ADDR_T_UNICAST       4
+       int                     refcount;
+       bool                    synced;
        struct rcu_head         rcu_head;
 };
 
@@ -738,10 +741,11 @@ struct net_device
        unsigned char           addr_len;       /* hardware address length      
*/
        unsigned short          dev_id;         /* for shared network cards */
 
-       spinlock_t              addr_list_lock;
-       struct dev_addr_list    *uc_list;       /* Secondary unicast mac 
addresses */
+       struct list_head        uc_list;        /* Secondary unicast mac
+                                                  addresses */
        int                     uc_count;       /* Number of installed ucasts   
*/
        int                     uc_promisc;
+       spinlock_t              addr_list_lock;
        struct dev_addr_list    *mc_list;       /* Multicast mac addresses      
*/
        int                     mc_count;       /* Number of installed mcasts   
*/
        unsigned int            promiscuity;
@@ -1816,8 +1820,8 @@ extern int dev_addr_del_multiple(struct net_device 
*to_dev,
 /* Functions used for secondary unicast and multicast support */
 extern void            dev_set_rx_mode(struct net_device *dev);
 extern void            __dev_set_rx_mode(struct net_device *dev);
-extern int             dev_unicast_delete(struct net_device *dev, void *addr, 
int alen);
-extern int             dev_unicast_add(struct net_device *dev, void *addr, int 
alen);
+extern int             dev_unicast_delete(struct net_device *dev, void *addr);
+extern int             dev_unicast_add(struct net_device *dev, void *addr);
 extern int             dev_unicast_sync(struct net_device *to, struct 
net_device *from);
 extern void            dev_unicast_unsync(struct net_device *to, struct 
net_device *from);
 extern int             dev_mc_delete(struct net_device *dev, void *addr, int 
alen, int all);
diff --git a/libdde_linux26/lib/src/net/core/dev.c 
b/libdde_linux26/lib/src/net/core/dev.c
index 6d193de..958345b 100644
--- a/libdde_linux26/lib/src/net/core/dev.c
+++ b/libdde_linux26/lib/src/net/core/dev.c
@@ -3399,8 +3399,9 @@ void dev_set_rx_mode(struct net_device *dev)
 
 /* hw addresses list handling functions */
 
-static int __hw_addr_add(struct list_head *list, unsigned char *addr,
-                        int addr_len, unsigned char addr_type)
+static int __hw_addr_add(struct list_head *list, int *delta,
+                        unsigned char *addr, int addr_len,
+                        unsigned char addr_type)
 {
        struct netdev_hw_addr *ha;
        int alloc_size;
@@ -3408,6 +3409,15 @@ static int __hw_addr_add(struct list_head *list, 
unsigned char *addr,
        if (addr_len > MAX_ADDR_LEN)
                return -EINVAL;
 
+       list_for_each_entry(ha, list, list) {
+               if (!memcmp(ha->addr, addr, addr_len) &&
+                   ha->type == addr_type) {
+                       ha->refcount++;
+                       return 0;
+               }
+       }
+
+
        alloc_size = sizeof(*ha);
        if (alloc_size < L1_CACHE_BYTES)
                alloc_size = L1_CACHE_BYTES;
@@ -3416,7 +3426,11 @@ static int __hw_addr_add(struct list_head *list, 
unsigned char *addr,
                return -ENOMEM;
        memcpy(ha->addr, addr, addr_len);
        ha->type = addr_type;
+       ha->refcount = 1;
+       ha->synced = false;
        list_add_tail_rcu(&ha->list, list);
+       if (delta)
+               (*delta)++;
        return 0;
 }
 
@@ -3428,29 +3442,30 @@ static void ha_rcu_free(struct rcu_head *head)
        kfree(ha);
 }
 
-static int __hw_addr_del_ii(struct list_head *list, unsigned char *addr,
-                           int addr_len, unsigned char addr_type,
-                           int ignore_index)
+static int __hw_addr_del(struct list_head *list, int *delta,
+                        unsigned char *addr, int addr_len,
+                        unsigned char addr_type)
 {
        struct netdev_hw_addr *ha;
-       int i = 0;
 
        list_for_each_entry(ha, list, list) {
-               if (i++ != ignore_index &&
-                   !memcmp(ha->addr, addr, addr_len) &&
+               if (!memcmp(ha->addr, addr, addr_len) &&
                    (ha->type == addr_type || !addr_type)) {
+                       if (--ha->refcount)
+                               return 0;
                        list_del_rcu(&ha->list);
                        call_rcu(&ha->rcu_head, ha_rcu_free);
+                       if (delta)
+                               (*delta)--;
                        return 0;
                }
        }
        return -ENOENT;
 }
 
-static int __hw_addr_add_multiple_ii(struct list_head *to_list,
-                                    struct list_head *from_list,
-                                    int addr_len, unsigned char addr_type,
-                                    int ignore_index)
+static int __hw_addr_add_multiple(struct list_head *to_list, int *to_delta,
+                                 struct list_head *from_list, int addr_len,
+                                 unsigned char addr_type)
 {
        int err;
        struct netdev_hw_addr *ha, *ha2;
@@ -3458,7 +3473,8 @@ static int __hw_addr_add_multiple_ii(struct list_head 
*to_list,
 
        list_for_each_entry(ha, from_list, list) {
                type = addr_type ? addr_type : ha->type;
-               err = __hw_addr_add(to_list, ha->addr, addr_len, type);
+               err = __hw_addr_add(to_list, to_delta, ha->addr,
+                                   addr_len, type);
                if (err)
                        goto unroll;
        }
@@ -3469,27 +3485,69 @@ unroll:
                if (ha2 == ha)
                        break;
                type = addr_type ? addr_type : ha2->type;
-               __hw_addr_del_ii(to_list, ha2->addr, addr_len, type,
-                                ignore_index);
+               __hw_addr_del(to_list, to_delta, ha2->addr,
+                             addr_len, type);
        }
        return err;
 }
 
-static void __hw_addr_del_multiple_ii(struct list_head *to_list,
-                                     struct list_head *from_list,
-                                     int addr_len, unsigned char addr_type,
-                                     int ignore_index)
+static void __hw_addr_del_multiple(struct list_head *to_list, int *to_delta,
+                                  struct list_head *from_list, int addr_len,
+                                  unsigned char addr_type)
 {
        struct netdev_hw_addr *ha;
        unsigned char type;
 
        list_for_each_entry(ha, from_list, list) {
                type = addr_type ? addr_type : ha->type;
-               __hw_addr_del_ii(to_list, ha->addr, addr_len, addr_type,
-                                ignore_index);
+               __hw_addr_del(to_list, to_delta, ha->addr,
+                             addr_len, addr_type);
+       }
+}
+
+static int __hw_addr_sync(struct list_head *to_list, int *to_delta,
+                         struct list_head *from_list, int *from_delta,
+                         int addr_len)
+{
+       int err = 0;
+       struct netdev_hw_addr *ha, *tmp;
+
+       list_for_each_entry_safe(ha, tmp, from_list, list) {
+               if (!ha->synced) {
+                       err = __hw_addr_add(to_list, to_delta, ha->addr,
+                                           addr_len, ha->type);
+                       if (err)
+                               break;
+                       ha->synced = true;
+                       ha->refcount++;
+               } else if (ha->refcount == 1) {
+                       __hw_addr_del(to_list, to_delta, ha->addr,
+                                     addr_len, ha->type);
+                       __hw_addr_del(from_list, from_delta, ha->addr,
+                                     addr_len, ha->type);
+               }
        }
+       return err;
 }
 
+static void __hw_addr_unsync(struct list_head *to_list, int *to_delta,
+                            struct list_head *from_list, int *from_delta,
+                            int addr_len)
+{
+       struct netdev_hw_addr *ha, *tmp;
+
+       list_for_each_entry_safe(ha, tmp, from_list, list) {
+               if (ha->synced) {
+                       __hw_addr_del(to_list, to_delta, ha->addr,
+                                     addr_len, ha->type);
+                       ha->synced = false;
+                       __hw_addr_del(from_list, from_delta, ha->addr,
+                                     addr_len, ha->type);
+               }
+       }
+}
+
+
 static void __hw_addr_flush(struct list_head *list)
 {
        struct netdev_hw_addr *ha, *tmp;
@@ -3520,7 +3578,7 @@ static int dev_addr_init(struct net_device *dev)
 
        INIT_LIST_HEAD(&dev->dev_addr_list);
        memset(addr, 0, sizeof(*addr));
-       err = __hw_addr_add(&dev->dev_addr_list, addr, sizeof(*addr),
+       err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(*addr),
                            NETDEV_HW_ADDR_T_LAN);
        if (!err) {
                /*
@@ -3552,7 +3610,7 @@ int dev_addr_add(struct net_device *dev, unsigned char 
*addr,
 
        ASSERT_RTNL();
 
-       err = __hw_addr_add(&dev->dev_addr_list, addr, dev->addr_len,
+       err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, dev->addr_len,
                            addr_type);
        if (!err)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
@@ -3575,11 +3633,20 @@ int dev_addr_del(struct net_device *dev, unsigned char 
*addr,
                 unsigned char addr_type)
 {
        int err;
+       struct netdev_hw_addr *ha;
 
        ASSERT_RTNL();
 
-       err = __hw_addr_del_ii(&dev->dev_addr_list, addr, dev->addr_len,
-                              addr_type, 0);
+       /*
+        * We can not remove the first address from the list because
+        * dev->dev_addr points to that.
+        */
+       ha = list_first_entry(&dev->dev_addr_list, struct netdev_hw_addr, list);
+       if (ha->addr == dev->dev_addr && ha->refcount == 1)
+               return -ENOENT;
+
+       err = __hw_addr_del(&dev->dev_addr_list, NULL, addr, dev->addr_len,
+                           addr_type);
        if (!err)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
        return err;
@@ -3606,9 +3673,9 @@ int dev_addr_add_multiple(struct net_device *to_dev,
 
        if (from_dev->addr_len != to_dev->addr_len)
                return -EINVAL;
-       err = __hw_addr_add_multiple_ii(&to_dev->dev_addr_list,
-                                       &from_dev->dev_addr_list,
-                                       to_dev->addr_len, addr_type, 0);
+       err = __hw_addr_add_multiple(&to_dev->dev_addr_list, NULL,
+                                    &from_dev->dev_addr_list,
+                                    to_dev->addr_len, addr_type);
        if (!err)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
        return err;
@@ -3633,9 +3700,9 @@ int dev_addr_del_multiple(struct net_device *to_dev,
 
        if (from_dev->addr_len != to_dev->addr_len)
                return -EINVAL;
-       __hw_addr_del_multiple_ii(&to_dev->dev_addr_list,
-                                 &from_dev->dev_addr_list,
-                                 to_dev->addr_len, addr_type, 0);
+       __hw_addr_del_multiple(&to_dev->dev_addr_list, NULL,
+                              &from_dev->dev_addr_list,
+                              to_dev->addr_len, addr_type);
        call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
        return 0;
 }
@@ -3705,24 +3772,22 @@ int __dev_addr_add(struct dev_addr_list **list, int 
*count,
  *     dev_unicast_delete      - Release secondary unicast address.
  *     @dev: device
  *     @addr: address to delete
- *     @alen: length of @addr
  *
  *     Release reference to a secondary unicast address and remove it
  *     from the device if the reference count drops to zero.
  *
  *     The caller must hold the rtnl_mutex.
  */
-int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
+int dev_unicast_delete(struct net_device *dev, void *addr)
 {
        int err;
 
        ASSERT_RTNL();
 
-       netif_addr_lock_bh(dev);
-       err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+       err = __hw_addr_del(&dev->uc_list, &dev->uc_count, addr,
+                           dev->addr_len, NETDEV_HW_ADDR_T_UNICAST);
        if (!err)
                __dev_set_rx_mode(dev);
-       netif_addr_unlock_bh(dev);
        return err;
 }
 EXPORT_SYMBOL(dev_unicast_delete);
@@ -3731,24 +3796,22 @@ EXPORT_SYMBOL(dev_unicast_delete);
  *     dev_unicast_add         - add a secondary unicast address
  *     @dev: device
  *     @addr: address to add
- *     @alen: length of @addr
  *
  *     Add a secondary unicast address to the device or increase
  *     the reference count if it already exists.
  *
  *     The caller must hold the rtnl_mutex.
  */
-int dev_unicast_add(struct net_device *dev, void *addr, int alen)
+int dev_unicast_add(struct net_device *dev, void *addr)
 {
        int err;
 
        ASSERT_RTNL();
 
-       netif_addr_lock_bh(dev);
-       err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+       err = __hw_addr_add(&dev->uc_list, &dev->uc_count, addr,
+                           dev->addr_len, NETDEV_HW_ADDR_T_UNICAST);
        if (!err)
                __dev_set_rx_mode(dev);
-       netif_addr_unlock_bh(dev);
        return err;
 }
 EXPORT_SYMBOL(dev_unicast_add);
@@ -3805,8 +3868,7 @@ void __dev_addr_unsync(struct dev_addr_list **to, int 
*to_count,
  *     @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_addr_lock_bh.
+ *     addresses that have no users left.
  *
  *     This function is intended to be called from the dev->set_rx_mode
  *     function of layered software devices.
@@ -3815,12 +3877,15 @@ int dev_unicast_sync(struct net_device *to, struct 
net_device *from)
 {
        int err = 0;
 
-       netif_addr_lock_bh(to);
-       err = __dev_addr_sync(&to->uc_list, &to->uc_count,
-                             &from->uc_list, &from->uc_count);
+       ASSERT_RTNL();
+
+       if (to->addr_len != from->addr_len)
+               return -EINVAL;
+
+       err = __hw_addr_sync(&to->uc_list, &to->uc_count,
+                            &from->uc_list, &from->uc_count, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
-       netif_addr_unlock_bh(to);
        return err;
 }
 EXPORT_SYMBOL(dev_unicast_sync);
@@ -3836,18 +3901,33 @@ EXPORT_SYMBOL(dev_unicast_sync);
  */
 void dev_unicast_unsync(struct net_device *to, struct net_device *from)
 {
-       netif_addr_lock_bh(from);
-       netif_addr_lock(to);
+       ASSERT_RTNL();
 
-       __dev_addr_unsync(&to->uc_list, &to->uc_count,
-                         &from->uc_list, &from->uc_count);
-       __dev_set_rx_mode(to);
+       if (to->addr_len != from->addr_len)
+               return;
 
-       netif_addr_unlock(to);
-       netif_addr_unlock_bh(from);
+       __hw_addr_unsync(&to->uc_list, &to->uc_count,
+                        &from->uc_list, &from->uc_count, to->addr_len);
+       __dev_set_rx_mode(to);
 }
 EXPORT_SYMBOL(dev_unicast_unsync);
 
+static void dev_unicast_flush(struct net_device *dev)
+{
+       /* rtnl_mutex must be held here */
+
+       __hw_addr_flush(&dev->uc_list);
+       dev->uc_count = 0;
+}
+
+static void dev_unicast_init(struct net_device *dev)
+{
+       /* rtnl_mutex must be held here */
+
+       INIT_LIST_HEAD(&dev->uc_list);
+}
+
+
 static void __dev_addr_discard(struct dev_addr_list **list)
 {
        struct dev_addr_list *tmp;
@@ -3866,9 +3946,6 @@ static void dev_addr_discard(struct net_device *dev)
 {
        netif_addr_lock_bh(dev);
 
-       __dev_addr_discard(&dev->uc_list);
-       dev->uc_count = 0;
-
        __dev_addr_discard(&dev->mc_list);
        dev->mc_count = 0;
 
@@ -4459,6 +4536,7 @@ static void rollback_registered(struct net_device *dev)
        /*
         *      Flush the unicast and multicast chains
         */
+       dev_unicast_flush(dev);
        dev_addr_discard(dev);
 
        if (dev->netdev_ops->ndo_uninit)
@@ -4975,6 +5053,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const 
char *name,
        dev = (struct net_device *)
                (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
        dev->padded = (char *)dev - (char *)p;
+       dev_unicast_init(dev);
+
        dev_net_set(dev, &init_net);
 
        dev->_tx = tx;
@@ -5173,6 +5253,7 @@ int dev_change_net_namespace(struct net_device *dev, 
struct net *net, const char
        /*
         *      Flush the unicast and multicast chains
         */
+       dev_unicast_flush(dev);
        dev_addr_discard(dev);
 
        netdev_unregister_kobject(dev);

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]