* from the bridge.
                 */
                if ((hw->features & STP_SUPPORT) && !promiscuous &&
-                               dev->br_port) {
+                   (dev->priv_flags & IFF_BRIDGE_PORT)) {
                        struct ksz_switch *sw = hw->ksz_switch;
                        int port = priv->port.first_port;
 
 
 #endif
 
        /* Device is being bridged */
-       /* if (net_dev->br_port != NULL)
+       /* if (net_dev->priv_flags & IFF_BRIDGE_PORT)
                return 0; */
 
        return 1;
 
 #define IFF_IN_NETPOLL 0x1000          /* whether we are processing netpoll */
 #define IFF_DISABLE_NETPOLL    0x2000  /* disable netpoll at run-time */
 #define IFF_MACVLAN_PORT       0x4000  /* device used as macvlan port */
+#define IFF_BRIDGE_PORT        0x8000          /* device used as bridge port */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
 
        /* mid-layer private */
        void                    *ml_priv;
 
-       /* bridge stuff */
-       struct net_bridge_port  *br_port;
        /* GARP */
        struct garp_port        *garp_port;
 
 
        struct net_bridge_fdb_entry *fdb;
        int ret;
 
-       if (!dev->br_port)
+       if (!br_port_exists(dev))
                return 0;
 
        rcu_read_lock();
-       fdb = __br_fdb_get(dev->br_port->br, addr);
+       fdb = __br_fdb_get(br_port_get_rcu(dev)->br, addr);
        ret = fdb && fdb->dst->dev != dev &&
                fdb->dst->state == BR_STATE_FORWARDING;
        rcu_read_unlock();
 
 
        list_del_rcu(&p->list);
 
+       dev->priv_flags &= ~IFF_BRIDGE_PORT;
+
        netdev_rx_handler_unregister(dev);
-       rcu_assign_pointer(dev->br_port, NULL);
 
        br_multicast_del_port(p);
 
                return -ELOOP;
 
        /* Device is already being bridged */
-       if (dev->br_port != NULL)
+       if (br_port_exists(dev))
                return -EBUSY;
 
        /* No bridging devices that dislike that (e.g. wireless) */
        if (br_netpoll_info(br) && ((err = br_netpoll_enable(p))))
                goto err3;
 
-       rcu_assign_pointer(dev->br_port, p);
-
-       err = netdev_rx_handler_register(dev, br_handle_frame, NULL);
+       err = netdev_rx_handler_register(dev, br_handle_frame, p);
        if (err)
-               goto err4;
+               goto err3;
+
+       dev->priv_flags |= IFF_BRIDGE_PORT;
 
        dev_disable_lro(dev);
 
        kobject_uevent(&p->kobj, KOBJ_ADD);
 
        return 0;
-err4:
-       rcu_assign_pointer(dev->br_port, NULL);
 err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
 /* called with RTNL */
 int br_del_if(struct net_bridge *br, struct net_device *dev)
 {
-       struct net_bridge_port *p = dev->br_port;
+       struct net_bridge_port *p;
+
+       if (!br_port_exists(dev))
+               return -EINVAL;
 
-       if (!p || p->br != br)
+       p = br_port_get(dev);
+       if (p->br != br)
                return -EINVAL;
 
        del_nbp(p);
 
 int br_handle_frame_finish(struct sk_buff *skb)
 {
        const unsigned char *dest = eth_hdr(skb)->h_dest;
-       struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
+       struct net_bridge_port *p = br_port_get_rcu(skb->dev);
        struct net_bridge *br;
        struct net_bridge_fdb_entry *dst;
        struct net_bridge_mdb_entry *mdst;
 /* note: already called with rcu_read_lock (preempt_disabled) */
 static int br_handle_local_finish(struct sk_buff *skb)
 {
-       struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
+       struct net_bridge_port *p = br_port_get_rcu(skb->dev);
 
-       if (p)
-               br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+       br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
        return 0;        /* process further */
 }
 
        if (!skb)
                return NULL;
 
-       p = rcu_dereference(skb->dev->br_port);
+       p = br_port_get_rcu(skb->dev);
 
        if (unlikely(is_link_local(dest))) {
                /* Pause frames shouldn't be passed up by driver anyway */
 
 
 static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
 {
-       struct net_bridge_port *port = rcu_dereference(dev->br_port);
-
-       return port ? &port->br->fake_rtable : NULL;
+       if (!br_port_exists(dev))
+               return NULL;
+       return &br_port_get_rcu(dev)->br->fake_rtable;
 }
 
 static inline struct net_device *bridge_parent(const struct net_device *dev)
 {
-       struct net_bridge_port *port = rcu_dereference(dev->br_port);
+       if (!br_port_exists(dev))
+               return NULL;
 
-       return port ? port->br->dev : NULL;
+       return br_port_get_rcu(dev)->br->dev;
 }
 
 static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
 
        idx = 0;
        for_each_netdev(net, dev) {
                /* not a bridge port */
-               if (dev->br_port == NULL || idx < cb->args[0])
+               if (!br_port_exists(dev) || idx < cb->args[0])
                        goto skip;
 
-               if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid,
+               if (br_fill_ifinfo(skb, br_port_get(dev),
+                                  NETLINK_CB(cb->skb).pid,
                                   cb->nlh->nlmsg_seq, RTM_NEWLINK,
                                   NLM_F_MULTI) < 0)
                        break;
        if (!dev)
                return -ENODEV;
 
-       p = dev->br_port;
-       if (!p)
+       if (!br_port_exists(dev))
                return -EINVAL;
+       p = br_port_get(dev);
 
        /* if kernel STP is running, don't allow changes */
        if (p->br->stp_enabled == BR_KERNEL_STP)
 
 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
 {
        struct net_device *dev = ptr;
-       struct net_bridge_port *p = dev->br_port;
+       struct net_bridge_port *p = br_port_get(dev);
        struct net_bridge *br;
        int err;
 
        /* not a port of a bridge */
-       if (p == NULL)
+       if (!br_port_exists(dev))
                return NOTIFY_DONE;
 
+       p = br_port_get(dev);
        br = p->br;
 
        switch (event) {
 
 #endif
 };
 
+#define br_port_get_rcu(dev) \
+       ((struct net_bridge_port *) rcu_dereference(dev->rx_handler_data))
+#define br_port_get(dev) ((struct net_bridge_port *) dev->rx_handler_data)
+#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
+
 struct br_cpu_netstats {
        unsigned long   rx_packets;
        unsigned long   rx_bytes;
 
                struct net_device *dev)
 {
        const unsigned char *dest = eth_hdr(skb)->h_dest;
-       struct net_bridge_port *p = rcu_dereference(dev->br_port);
+       struct net_bridge_port *p;
        struct net_bridge *br;
        const unsigned char *buf;
 
-       if (!p)
+       if (!br_port_exists(dev))
                goto err;
+       p = br_port_get_rcu(dev);
 
        if (!pskb_may_pull(skb, 4))
                goto err;
 
                return EBT_DROP;
 
        if (par->hooknum != NF_BR_BROUTING)
+               /* rcu_read_lock()ed by nf_hook_slow */
                memcpy(eth_hdr(skb)->h_dest,
-                      par->in->br_port->br->dev->dev_addr, ETH_ALEN);
+                      br_port_get_rcu(par->in)->br->dev->dev_addr, ETH_ALEN);
        else
                memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN);
        skb->pkt_type = PACKET_HOST;
 
        if (in) {
                strcpy(pm->physindev, in->name);
                /* If in isn't a bridge, then physindev==indev */
-               if (in->br_port)
-                       strcpy(pm->indev, in->br_port->br->dev->name);
+               if (br_port_exists(in))
+                       /* rcu_read_lock()ed by nf_hook_slow */
+                       strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
                else
                        strcpy(pm->indev, in->name);
        } else
        if (out) {
                /* If out exists, then out is a bridge port */
                strcpy(pm->physoutdev, out->name);
-               strcpy(pm->outdev, out->br_port->br->dev->name);
+               /* rcu_read_lock()ed by nf_hook_slow */
+               strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
        } else
                pm->outdev[0] = pm->physoutdev[0] = '\0';
 
 
                return 1;
        if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
                return 1;
-       if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
-          e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
+       /* rcu_read_lock()ed by nf_hook_slow */
+       if (in && br_port_exists(in) &&
+           FWINV2(ebt_dev_check(e->logical_in, br_port_get_rcu(in)->br->dev),
+                  EBT_ILOGICALIN))
                return 1;
-       if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
-          e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
+       if (out && br_port_exists(out) &&
+           FWINV2(ebt_dev_check(e->logical_out, br_port_get_rcu(out)->br->dev),
+                  EBT_ILOGICALOUT))
                return 1;
 
        if (e->bitmask & EBT_SOURCEMAC) {
 
        if (master->priv_flags & IFF_MASTER_ARPMON)
                dev->last_rx = jiffies;
 
-       if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
+       if ((master->priv_flags & IFF_MASTER_ALB) &&
+           (master->priv_flags & IFF_BRIDGE_PORT)) {
                /* Do address unmangle. The local destination address
                 * will be always the one master has. Provides the right
                 * functionality in a bridge.
 
                        NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
                                     htonl(indev->ifindex));
                        /* this is the bridge group "brX" */
+                       /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
                        NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
-                                    htonl(indev->br_port->br->dev->ifindex));
+                                    htonl(br_port_get_rcu(indev)->br->dev->ifindex));
                } else {
                        /* Case 2: indev is bridge group, we need to look for
                         * physical device (when called from ipv4) */
                        NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
                                     htonl(outdev->ifindex));
                        /* this is the bridge group "brX" */
+                       /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
                        NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
-                                    htonl(outdev->br_port->br->dev->ifindex));
+                                    htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
                } else {
                        /* Case 2: indev is a bridge group, we need to look
                         * for physical device (when called from ipv4) */
 
                        NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
                                     htonl(indev->ifindex));
                        /* this is the bridge group "brX" */
+                       /* rcu_read_lock()ed by __nf_queue */
                        NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
-                                    htonl(indev->br_port->br->dev->ifindex));
+                                    htonl(br_port_get_rcu(indev)->br->dev->ifindex));
                } else {
                        /* Case 2: indev is bridge group, we need to look for
                         * physical device (when called from ipv4) */
                        NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
                                     htonl(outdev->ifindex));
                        /* this is the bridge group "brX" */
+                       /* rcu_read_lock()ed by __nf_queue */
                        NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
-                                    htonl(outdev->br_port->br->dev->ifindex));
+                                    htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
                } else {
                        /* Case 2: outdev is bridge group, we need to look for
                         * physical output device (when called from ipv4) */
 
                               enum nl80211_iftype iftype)
 {
        if (!use_4addr) {
-               if (netdev && netdev->br_port)
+               if (netdev && (netdev->priv_flags & IFF_BRIDGE_PORT))
                        return -EBUSY;
                return 0;
        }
 
                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))
+       if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
+           (ntype == NL80211_IFTYPE_ADHOC || ntype == NL80211_IFTYPE_STATION))
                return -EBUSY;
 
        if (ntype != otype) {