Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil...
[pandora-kernel.git] / net / bridge / br_fdb.c
index 24396b9..d9f0486 100644 (file)
@@ -86,8 +86,8 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
                                struct net_bridge_port *op;
                                list_for_each_entry(op, &br->port_list, list) {
                                        if (op != p && 
-                                           !memcmp(op->dev->dev_addr,
-                                                   f->addr.addr, ETH_ALEN)) {
+                                           !compare_ether_addr(op->dev->dev_addr,
+                                                               f->addr.addr)) {
                                                f->dst = op;
                                                goto insert;
                                        }
@@ -128,7 +128,10 @@ void br_fdb_cleanup(unsigned long _data)
        mod_timer(&br->gc_timer, jiffies + HZ/10);
 }
 
-void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
+
+void br_fdb_delete_by_port(struct net_bridge *br,
+                          const struct net_bridge_port *p,
+                          int do_all)
 {
        int i;
 
@@ -142,6 +145,8 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
                        if (f->dst != p) 
                                continue;
 
+                       if (f->is_static && !do_all)
+                               continue;
                        /*
                         * if multiple ports all have the same device address
                         * then when one port is deleted, assign
@@ -151,8 +156,8 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
                                struct net_bridge_port *op;
                                list_for_each_entry(op, &br->port_list, list) {
                                        if (op != p && 
-                                           !memcmp(op->dev->dev_addr,
-                                                   f->addr.addr, ETH_ALEN)) {
+                                           !compare_ether_addr(op->dev->dev_addr,
+                                                               f->addr.addr)) {
                                                f->dst = op;
                                                goto skip_delete;
                                        }
@@ -174,7 +179,7 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
        struct net_bridge_fdb_entry *fdb;
 
        hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
-               if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
+               if (!compare_ether_addr(fdb->addr.addr, addr)) {
                        if (unlikely(has_expired(br, fdb)))
                                break;
                        return fdb;
@@ -264,7 +269,7 @@ static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
        struct net_bridge_fdb_entry *fdb;
 
        hlist_for_each_entry_rcu(fdb, h, head, hlist) {
-               if (!memcmp(fdb->addr.addr, addr, ETH_ALEN))
+               if (!compare_ether_addr(fdb->addr.addr, addr))
                        return fdb;
        }
        return NULL;
@@ -341,7 +346,6 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
        if (hold_time(br) == 0)
                return;
 
-       rcu_read_lock();
        fdb = fdb_find(head, addr);
        if (likely(fdb)) {
                /* attempt to update an entry for a local interface */
@@ -356,13 +360,12 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
                        fdb->ageing_timer = jiffies;
                }
        } else {
-               spin_lock_bh(&br->hash_lock);
+               spin_lock(&br->hash_lock);
                if (!fdb_find(head, addr))
                        fdb_create(head, source, addr, 0);
                /* else  we lose race and someone else inserts
                 * it first, don't bother updating
                 */
-               spin_unlock_bh(&br->hash_lock);
+               spin_unlock(&br->hash_lock);
        }
-       rcu_read_unlock();
 }