#define IFF_XMIT_DST_RELEASE 0x400     /* dev_hard_start_xmit() is allowed to
                                         * release skb->dst
                                         */
+#define IFF_DONT_BRIDGE 0x800          /* disallow bridging this ether dev */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
 
        if (dev->br_port != NULL)
                return -EBUSY;
 
+       /* No bridging devices that dislike that (e.g. wireless) */
+       if (dev->priv_flags & IFF_DONT_BRIDGE)
+               return -EOPNOTSUPP;
+
        p = new_nbp(br, dev);
        if (IS_ERR(p))
                return PTR_ERR(p);
 
 #endif
                if (!dev->ethtool_ops)
                        dev->ethtool_ops = &cfg80211_ethtool_ops;
+
+               if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+                    wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
+                       dev->priv_flags |= IFF_DONT_BRIDGE;
                break;
        case NETDEV_GOING_DOWN:
                switch (wdev->iftype) {
 
 }
 
 static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
-                              u8 use_4addr, enum nl80211_iftype iftype)
+                              struct net_device *netdev, u8 use_4addr,
+                              enum nl80211_iftype iftype)
 {
-       if (!use_4addr)
+       if (!use_4addr) {
+               if (netdev && netdev->br_port)
+                       return -EBUSY;
                return 0;
+       }
 
        switch (iftype) {
        case NL80211_IFTYPE_AP_VLAN:
        if (info->attrs[NL80211_ATTR_4ADDR]) {
                params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
                change = true;
-               err = nl80211_valid_4addr(rdev, params.use_4addr, ntype);
+               err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
                if (err)
                        goto unlock;
        } else {
 
        if (info->attrs[NL80211_ATTR_4ADDR]) {
                params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
-               err = nl80211_valid_4addr(rdev, params.use_4addr, type);
+               err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
                if (err)
                        goto unlock;
        }
 
            !(rdev->wiphy.interface_modes & (1 << ntype)))
                return -EOPNOTSUPP;
 
+       /* if it's part of a bridge, reject changing type to station/ibss */
+       if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC ||
+                            ntype == NL80211_IFTYPE_STATION))
+               return -EBUSY;
+
        if (ntype != otype) {
                dev->ieee80211_ptr->use_4addr = false;
 
        if (!err && params && params->use_4addr != -1)
                dev->ieee80211_ptr->use_4addr = params->use_4addr;
 
+       if (!err) {
+               dev->priv_flags &= ~IFF_DONT_BRIDGE;
+               switch (ntype) {
+               case NL80211_IFTYPE_STATION:
+                       if (dev->ieee80211_ptr->use_4addr)
+                               break;
+                       /* fall through */
+               case NL80211_IFTYPE_ADHOC:
+                       dev->priv_flags |= IFF_DONT_BRIDGE;
+                       break;
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_WDS:
+               case NL80211_IFTYPE_MESH_POINT:
+                       /* bridging OK */
+                       break;
+               case NL80211_IFTYPE_MONITOR:
+                       /* monitor can't bridge anyway */
+                       break;
+               case NL80211_IFTYPE_UNSPECIFIED:
+               case __NL80211_IFTYPE_AFTER_LAST:
+                       /* not happening */
+                       break;
+               }
+       }
+
        return err;
 }