Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / bridge / br_multicast.c
index d7e103e3538a6d165a76c96ccb07659a1d5abfb9..742a6c27d7a222bc3c53c288b4a6915194310fe6 100644 (file)
@@ -37,6 +37,8 @@
 
 static void br_multicast_start_querier(struct net_bridge *br,
                                       struct bridge_mcast_own_query *query);
+static void br_multicast_add_router(struct net_bridge *br,
+                                   struct net_bridge_port *port);
 unsigned int br_mdb_rehash_seq;
 
 static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -936,6 +938,8 @@ void br_multicast_enable_port(struct net_bridge_port *port)
 #if IS_ENABLED(CONFIG_IPV6)
        br_multicast_enable(&port->ip6_own_query);
 #endif
+       if (port->multicast_router == 2 && hlist_unhashed(&port->rlist))
+               br_multicast_add_router(br, port);
 
 out:
        spin_unlock(&br->multicast_lock);
@@ -1164,6 +1168,9 @@ static void br_multicast_add_router(struct net_bridge *br,
        struct net_bridge_port *p;
        struct hlist_node *slot = NULL;
 
+       if (!hlist_unhashed(&port->rlist))
+               return;
+
        hlist_for_each_entry(p, &br->router_list, rlist) {
                if ((unsigned long) port >= (unsigned long) p)
                        break;
@@ -1191,12 +1198,8 @@ static void br_multicast_mark_router(struct net_bridge *br,
        if (port->multicast_router != 1)
                return;
 
-       if (!hlist_unhashed(&port->rlist))
-               goto timer;
-
        br_multicast_add_router(br, port);
 
-timer:
        mod_timer(&port->multicast_router_timer,
                  now + br->multicast_querier_interval);
 }
@@ -1644,7 +1647,7 @@ static void br_multicast_query_expired(struct net_bridge *br,
        if (query->startup_sent < br->multicast_startup_query_count)
                query->startup_sent++;
 
-       RCU_INIT_POINTER(querier, NULL);
+       RCU_INIT_POINTER(querier->port, NULL);
        br_multicast_send_query(br, NULL, query);
        spin_unlock(&br->multicast_lock);
 }
@@ -1772,11 +1775,9 @@ out:
 
 int br_multicast_set_router(struct net_bridge *br, unsigned long val)
 {
-       int err = -ENOENT;
+       int err = -EINVAL;
 
        spin_lock_bh(&br->multicast_lock);
-       if (!netif_running(br->dev))
-               goto unlock;
 
        switch (val) {
        case 0:
@@ -1787,13 +1788,8 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val)
                br->multicast_router = val;
                err = 0;
                break;
-
-       default:
-               err = -EINVAL;
-               break;
        }
 
-unlock:
        spin_unlock_bh(&br->multicast_lock);
 
        return err;
@@ -1802,11 +1798,9 @@ unlock:
 int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
 {
        struct net_bridge *br = p->br;
-       int err = -ENOENT;
+       int err = -EINVAL;
 
        spin_lock(&br->multicast_lock);
-       if (!netif_running(br->dev) || p->state == BR_STATE_DISABLED)
-               goto unlock;
 
        switch (val) {
        case 0:
@@ -1828,13 +1822,8 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
 
                br_multicast_add_router(br, p);
                break;
-
-       default:
-               err = -EINVAL;
-               break;
        }
 
-unlock:
        spin_unlock(&br->multicast_lock);
 
        return err;
@@ -1939,15 +1928,11 @@ unlock:
 
 int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
 {
-       int err = -ENOENT;
+       int err = -EINVAL;
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
        spin_lock_bh(&br->multicast_lock);
-       if (!netif_running(br->dev))
-               goto unlock;
-
-       err = -EINVAL;
        if (!is_power_of_2(val))
                goto unlock;