{
 }
 
+static void br_dev_change_rx_flags(struct net_device *dev, int change)
+{
+       if (change & IFF_PROMISC)
+               br_manage_promisc(netdev_priv(dev));
+}
+
 static int br_dev_stop(struct net_device *dev)
 {
        struct net_bridge *br = netdev_priv(dev);
        .ndo_get_stats64         = br_get_stats64,
        .ndo_set_mac_address     = br_set_mac_address,
        .ndo_set_rx_mode         = br_dev_set_multicast_list,
+       .ndo_change_rx_flags     = br_dev_change_rx_flags,
        .ndo_change_mtu          = br_change_mtu,
        .ndo_do_ioctl            = br_dev_ioctl,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 
        spin_unlock_bh(&br->lock);
 }
 
+static void br_port_set_promisc(struct net_bridge_port *p)
+{
+       int err = 0;
+
+       if (br_promisc_port(p))
+               return;
+
+       err = dev_set_promiscuity(p->dev, 1);
+       if (err)
+               return;
+
+       br_fdb_unsync_static(p->br, p);
+       p->flags |= BR_PROMISC;
+}
+
+static void br_port_clear_promisc(struct net_bridge_port *p)
+{
+       int err;
+
+       /* Check if the port is already non-promisc or if it doesn't
+        * support UNICAST filtering.  Without unicast filtering support
+        * we'll end up re-enabling promisc mode anyway, so just check for
+        * it here.
+        */
+       if (!br_promisc_port(p) || !(p->dev->priv_flags & IFF_UNICAST_FLT))
+               return;
+
+       /* Since we'll be clearing the promisc mode, program the port
+        * first so that we don't have interruption in traffic.
+        */
+       err = br_fdb_sync_static(p->br, p);
+       if (err)
+               return;
+
+       dev_set_promiscuity(p->dev, -1);
+       p->flags &= ~BR_PROMISC;
+}
+
+/* When a port is added or removed or when certain port flags
+ * change, this function is called to automatically manage
+ * promiscuity setting of all the bridge ports.  We are always called
+ * under RTNL so can skip using rcu primitives.
+ */
+void br_manage_promisc(struct net_bridge *br)
+{
+       struct net_bridge_port *p;
+       bool set_all = false;
+
+       /* If vlan filtering is disabled or bridge interface is placed
+        * into promiscuous mode, place all ports in promiscuous mode.
+        */
+       if ((br->dev->flags & IFF_PROMISC) || !br_vlan_enabled(br))
+               set_all = true;
+
+       list_for_each_entry(p, &br->port_list, list) {
+               if (set_all) {
+                       br_port_set_promisc(p);
+               } else {
+                       /* If the number of auto-ports is <= 1, then all other
+                        * ports will have their output configuration
+                        * statically specified through fdbs.  Since ingress
+                        * on the auto-port becomes forwarding/egress to other
+                        * ports and egress configuration is statically known,
+                        * we can say that ingress configuration of the
+                        * auto-port is also statically known.
+                        * This lets us disable promiscuous mode and write
+                        * this config to hw.
+                        */
+                       if (br->auto_cnt <= br_auto_port(p))
+                               br_port_clear_promisc(p);
+                       else
+                               br_port_set_promisc(p);
+               }
+       }
+}
+
 static void nbp_update_port_count(struct net_bridge *br)
 {
        struct net_bridge_port *p;
                if (br_auto_port(p))
                        cnt++;
        }
-       br->auto_cnt = cnt;
+       if (br->auto_cnt != cnt) {
+               br->auto_cnt = cnt;
+               br_manage_promisc(br);
+       }
+}
+
+static void nbp_delete_promisc(struct net_bridge_port *p)
+{
+       /* If port is currently promiscous, unset promiscuity.
+        * Otherwise, it is a static port so remove all addresses
+        * from it.
+        */
+       dev_set_allmulti(p->dev, -1);
+       if (br_promisc_port(p))
+               dev_set_promiscuity(p->dev, -1);
+       else
+               br_fdb_unsync_static(p->br, p);
 }
 
 static void release_nbp(struct kobject *kobj)
 
        sysfs_remove_link(br->ifobj, p->dev->name);
 
-       dev_set_promiscuity(dev, -1);
+       nbp_delete_promisc(p);
 
        spin_lock_bh(&br->lock);
        br_stp_disable_port(p);
 
        br_ifinfo_notify(RTM_DELLINK, p);
 
-       nbp_vlan_flush(p);
-       br_fdb_delete_by_port(br, p, 1);
-
        list_del_rcu(&p->list);
 
+       nbp_vlan_flush(p);
+       br_fdb_delete_by_port(br, p, 1);
        nbp_update_port_count(br);
 
        dev->priv_flags &= ~IFF_BRIDGE_PORT;
        p->path_cost = port_cost(dev);
        p->priority = 0x8000 >> BR_PORT_BITS;
        p->port_no = index;
-       p->flags = BR_LEARNING | BR_FLOOD | BR_PROMISC;
+       p->flags = BR_LEARNING | BR_FLOOD;
        br_init_port(p);
        p->state = BR_STATE_DISABLED;
        br_stp_port_timer_init(p);
 
        call_netdevice_notifiers(NETDEV_JOIN, dev);
 
-       err = dev_set_promiscuity(dev, 1);
+       err = dev_set_allmulti(dev, 1);
        if (err)
                goto put_back;