void br_recalculate_fwd_mask(struct net_bridge *br);
 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
 int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
-void br_vlan_init(struct net_bridge *br);
+int br_vlan_init(struct net_bridge *br);
 int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
 void nbp_vlan_flush(struct net_bridge_port *port);
 bool nbp_vlan_find(struct net_bridge_port *port, u16 vid);
+int nbp_vlan_init(struct net_bridge_port *port);
 
 static inline struct net_port_vlans *br_get_vlan_info(
                                                const struct net_bridge *br)
 
 static inline u16 br_get_pvid(const struct net_port_vlans *v)
 {
+       if (!v)
+               return 0;
+
        smp_rmb();
        return v->pvid;
 }
 {
 }
 
-static inline void br_vlan_init(struct net_bridge *br)
+static inline int br_vlan_init(struct net_bridge *br)
 {
+       return 0;
 }
 
 static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
        return false;
 }
 
+static inline int nbp_vlan_init(struct net_bridge_port *port)
+{
+       return 0;
+}
+
 static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag)
 {
        return 0;
 
        goto unlock;
 }
 
+static bool vlan_default_pvid(struct net_port_vlans *pv, u16 vid)
+{
+       return pv && vid == pv->pvid && test_bit(vid, pv->untagged_bitmap);
+}
+
+static void br_vlan_disable_default_pvid(struct net_bridge *br)
+{
+       struct net_bridge_port *p;
+       u16 pvid = br->default_pvid;
+
+       /* Disable default_pvid on all ports where it is still
+        * configured.
+        */
+       if (vlan_default_pvid(br_get_vlan_info(br), pvid))
+               br_vlan_delete(br, pvid);
+
+       list_for_each_entry(p, &br->port_list, list) {
+               if (vlan_default_pvid(nbp_get_vlan_info(p), pvid))
+                       nbp_vlan_delete(p, pvid);
+       }
+
+       br->default_pvid = 0;
+}
+
+static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
+{
+       struct net_bridge_port *p;
+       u16 old_pvid;
+       int err = 0;
+       unsigned long *changed;
+
+       changed = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long),
+                         GFP_KERNEL);
+       if (!changed)
+               return -ENOMEM;
+
+       old_pvid = br->default_pvid;
+
+       /* Update default_pvid config only if we do not conflict with
+        * user configuration.
+        */
+       if ((!old_pvid || vlan_default_pvid(br_get_vlan_info(br), old_pvid)) &&
+           !br_vlan_find(br, pvid)) {
+               err = br_vlan_add(br, pvid,
+                                 BRIDGE_VLAN_INFO_PVID |
+                                 BRIDGE_VLAN_INFO_UNTAGGED);
+               if (err)
+                       goto out;
+               br_vlan_delete(br, old_pvid);
+               set_bit(0, changed);
+       }
+
+       list_for_each_entry(p, &br->port_list, list) {
+               /* Update default_pvid config only if we do not conflict with
+                * user configuration.
+                */
+               if ((old_pvid &&
+                    !vlan_default_pvid(nbp_get_vlan_info(p), old_pvid)) ||
+                   nbp_vlan_find(p, pvid))
+                       continue;
+
+               err = nbp_vlan_add(p, pvid,
+                                  BRIDGE_VLAN_INFO_PVID |
+                                  BRIDGE_VLAN_INFO_UNTAGGED);
+               if (err)
+                       goto err_port;
+               nbp_vlan_delete(p, old_pvid);
+               set_bit(p->port_no, changed);
+       }
+
+       br->default_pvid = pvid;
+
+out:
+       kfree(changed);
+       return err;
+
+err_port:
+       list_for_each_entry_continue_reverse(p, &br->port_list, list) {
+               if (!test_bit(p->port_no, changed))
+                       continue;
+
+               if (old_pvid)
+                       nbp_vlan_add(p, old_pvid,
+                                    BRIDGE_VLAN_INFO_PVID |
+                                    BRIDGE_VLAN_INFO_UNTAGGED);
+               nbp_vlan_delete(p, pvid);
+       }
+
+       if (test_bit(0, changed)) {
+               if (old_pvid)
+                       br_vlan_add(br, old_pvid,
+                                   BRIDGE_VLAN_INFO_PVID |
+                                   BRIDGE_VLAN_INFO_UNTAGGED);
+               br_vlan_delete(br, pvid);
+       }
+       goto out;
+}
+
 int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
 {
        u16 pvid = val;
        int err = 0;
 
-       if (!val || val >= VLAN_VID_MASK)
+       if (val >= VLAN_VID_MASK)
                return -EINVAL;
 
        if (!rtnl_trylock())
                goto unlock;
        }
 
-       br->default_pvid = pvid;
+       if (!pvid)
+               br_vlan_disable_default_pvid(br);
+       else
+               err = __br_vlan_set_default_pvid(br, pvid);
 
 unlock:
        rtnl_unlock();
        return err;
 }
 
-void br_vlan_init(struct net_bridge *br)
+int br_vlan_init(struct net_bridge *br)
 {
        br->vlan_proto = htons(ETH_P_8021Q);
        br->default_pvid = 1;
+       return br_vlan_add(br, 1,
+                          BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED);
 }
 
 /* Must be protected by RTNL.
        rcu_read_unlock();
        return found;
 }
+
+int nbp_vlan_init(struct net_bridge_port *p)
+{
+       return p->br->default_pvid ?
+                       nbp_vlan_add(p, p->br->default_pvid,
+                                    BRIDGE_VLAN_INFO_PVID |
+                                    BRIDGE_VLAN_INFO_UNTAGGED) :
+                       0;
+}