aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2010-06-15 02:50:45 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-15 14:48:58 -0400
commitf350a0a87374418635689471606454abc7beaa3a (patch)
treec8210542a9848f6b5953b58d2ba1dbfb11715f14 /net
parenta35e2c1b6d90544b3c688783869817628e5f9607 (diff)
bridge: use rx_handler_data pointer to store net_bridge_port pointer
Register net_bridge_port pointer as rx_handler data pointer. As br_port is removed from struct net_device, another netdev priv_flag is added to indicate the device serves as a bridge port. Also rcuized pointers are now correctly dereferenced in br_fdb.c and in netfilter parts. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_fdb.c4
-rw-r--r--net/bridge/br_if.c23
-rw-r--r--net/bridge/br_input.c9
-rw-r--r--net/bridge/br_netfilter.c11
-rw-r--r--net/bridge/br_netlink.c9
-rw-r--r--net/bridge/br_notify.c5
-rw-r--r--net/bridge/br_private.h5
-rw-r--r--net/bridge/br_stp_bpdu.c5
-rw-r--r--net/bridge/netfilter/ebt_redirect.c3
-rw-r--r--net/bridge/netfilter/ebt_ulog.c8
-rw-r--r--net/bridge/netfilter/ebtables.c11
-rw-r--r--net/core/dev.c3
-rw-r--r--net/netfilter/nfnetlink_log.c6
-rw-r--r--net/netfilter/nfnetlink_queue.c6
-rw-r--r--net/wireless/nl80211.c2
-rw-r--r--net/wireless/util.c4
16 files changed, 68 insertions, 46 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 26637439965b..6818e609b2c0 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -242,11 +242,11 @@ int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
242 struct net_bridge_fdb_entry *fdb; 242 struct net_bridge_fdb_entry *fdb;
243 int ret; 243 int ret;
244 244
245 if (!dev->br_port) 245 if (!br_port_exists(dev))
246 return 0; 246 return 0;
247 247
248 rcu_read_lock(); 248 rcu_read_lock();
249 fdb = __br_fdb_get(dev->br_port->br, addr); 249 fdb = __br_fdb_get(br_port_get_rcu(dev)->br, addr);
250 ret = fdb && fdb->dst->dev != dev && 250 ret = fdb && fdb->dst->dev != dev &&
251 fdb->dst->state == BR_STATE_FORWARDING; 251 fdb->dst->state == BR_STATE_FORWARDING;
252 rcu_read_unlock(); 252 rcu_read_unlock();
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 0d142ed0bbe3..c03d2c3ff03e 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -147,8 +147,9 @@ static void del_nbp(struct net_bridge_port *p)
147 147
148 list_del_rcu(&p->list); 148 list_del_rcu(&p->list);
149 149
150 dev->priv_flags &= ~IFF_BRIDGE_PORT;
151
150 netdev_rx_handler_unregister(dev); 152 netdev_rx_handler_unregister(dev);
151 rcu_assign_pointer(dev->br_port, NULL);
152 153
153 br_multicast_del_port(p); 154 br_multicast_del_port(p);
154 155
@@ -400,7 +401,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
400 return -ELOOP; 401 return -ELOOP;
401 402
402 /* Device is already being bridged */ 403 /* Device is already being bridged */
403 if (dev->br_port != NULL) 404 if (br_port_exists(dev))
404 return -EBUSY; 405 return -EBUSY;
405 406
406 /* No bridging devices that dislike that (e.g. wireless) */ 407 /* No bridging devices that dislike that (e.g. wireless) */
@@ -431,11 +432,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
431 if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) 432 if (br_netpoll_info(br) && ((err = br_netpoll_enable(p))))
432 goto err3; 433 goto err3;
433 434
434 rcu_assign_pointer(dev->br_port, p); 435 err = netdev_rx_handler_register(dev, br_handle_frame, p);
435
436 err = netdev_rx_handler_register(dev, br_handle_frame, NULL);
437 if (err) 436 if (err)
438 goto err4; 437 goto err3;
438
439 dev->priv_flags |= IFF_BRIDGE_PORT;
439 440
440 dev_disable_lro(dev); 441 dev_disable_lro(dev);
441 442
@@ -457,8 +458,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
457 kobject_uevent(&p->kobj, KOBJ_ADD); 458 kobject_uevent(&p->kobj, KOBJ_ADD);
458 459
459 return 0; 460 return 0;
460err4:
461 rcu_assign_pointer(dev->br_port, NULL);
462err3: 461err3:
463 sysfs_remove_link(br->ifobj, p->dev->name); 462 sysfs_remove_link(br->ifobj, p->dev->name);
464err2: 463err2:
@@ -477,9 +476,13 @@ put_back:
477/* called with RTNL */ 476/* called with RTNL */
478int br_del_if(struct net_bridge *br, struct net_device *dev) 477int br_del_if(struct net_bridge *br, struct net_device *dev)
479{ 478{
480 struct net_bridge_port *p = dev->br_port; 479 struct net_bridge_port *p;
480
481 if (!br_port_exists(dev))
482 return -EINVAL;
481 483
482 if (!p || p->br != br) 484 p = br_port_get(dev);
485 if (p->br != br)
483 return -EINVAL; 486 return -EINVAL;
484 487
485 del_nbp(p); 488 del_nbp(p);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 99647d8f95c8..f076c9d79d5e 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -41,7 +41,7 @@ static int br_pass_frame_up(struct sk_buff *skb)
41int br_handle_frame_finish(struct sk_buff *skb) 41int br_handle_frame_finish(struct sk_buff *skb)
42{ 42{
43 const unsigned char *dest = eth_hdr(skb)->h_dest; 43 const unsigned char *dest = eth_hdr(skb)->h_dest;
44 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 44 struct net_bridge_port *p = br_port_get_rcu(skb->dev);
45 struct net_bridge *br; 45 struct net_bridge *br;
46 struct net_bridge_fdb_entry *dst; 46 struct net_bridge_fdb_entry *dst;
47 struct net_bridge_mdb_entry *mdst; 47 struct net_bridge_mdb_entry *mdst;
@@ -111,10 +111,9 @@ drop:
111/* note: already called with rcu_read_lock (preempt_disabled) */ 111/* note: already called with rcu_read_lock (preempt_disabled) */
112static int br_handle_local_finish(struct sk_buff *skb) 112static int br_handle_local_finish(struct sk_buff *skb)
113{ 113{
114 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 114 struct net_bridge_port *p = br_port_get_rcu(skb->dev);
115 115
116 if (p) 116 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
117 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
118 return 0; /* process further */ 117 return 0; /* process further */
119} 118}
120 119
@@ -151,7 +150,7 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb)
151 if (!skb) 150 if (!skb)
152 return NULL; 151 return NULL;
153 152
154 p = rcu_dereference(skb->dev->br_port); 153 p = br_port_get_rcu(skb->dev);
155 154
156 if (unlikely(is_link_local(dest))) { 155 if (unlikely(is_link_local(dest))) {
157 /* Pause frames shouldn't be passed up by driver anyway */ 156 /* Pause frames shouldn't be passed up by driver anyway */
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 0685b2558ab5..f54404ddee53 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -127,16 +127,17 @@ void br_netfilter_rtable_init(struct net_bridge *br)
127 127
128static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) 128static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
129{ 129{
130 struct net_bridge_port *port = rcu_dereference(dev->br_port); 130 if (!br_port_exists(dev))
131 131 return NULL;
132 return port ? &port->br->fake_rtable : NULL; 132 return &br_port_get_rcu(dev)->br->fake_rtable;
133} 133}
134 134
135static inline struct net_device *bridge_parent(const struct net_device *dev) 135static inline struct net_device *bridge_parent(const struct net_device *dev)
136{ 136{
137 struct net_bridge_port *port = rcu_dereference(dev->br_port); 137 if (!br_port_exists(dev))
138 return NULL;
138 139
139 return port ? port->br->dev : NULL; 140 return br_port_get_rcu(dev)->br->dev;
140} 141}
141 142
142static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) 143static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index fe0a79018ab2..4a6a378c84e3 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -120,10 +120,11 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
120 idx = 0; 120 idx = 0;
121 for_each_netdev(net, dev) { 121 for_each_netdev(net, dev) {
122 /* not a bridge port */ 122 /* not a bridge port */
123 if (dev->br_port == NULL || idx < cb->args[0]) 123 if (!br_port_exists(dev) || idx < cb->args[0])
124 goto skip; 124 goto skip;
125 125
126 if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid, 126 if (br_fill_ifinfo(skb, br_port_get(dev),
127 NETLINK_CB(cb->skb).pid,
127 cb->nlh->nlmsg_seq, RTM_NEWLINK, 128 cb->nlh->nlmsg_seq, RTM_NEWLINK,
128 NLM_F_MULTI) < 0) 129 NLM_F_MULTI) < 0)
129 break; 130 break;
@@ -168,9 +169,9 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
168 if (!dev) 169 if (!dev)
169 return -ENODEV; 170 return -ENODEV;
170 171
171 p = dev->br_port; 172 if (!br_port_exists(dev))
172 if (!p)
173 return -EINVAL; 173 return -EINVAL;
174 p = br_port_get(dev);
174 175
175 /* if kernel STP is running, don't allow changes */ 176 /* if kernel STP is running, don't allow changes */
176 if (p->br->stp_enabled == BR_KERNEL_STP) 177 if (p->br->stp_enabled == BR_KERNEL_STP)
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 717e1fd6133c..404d4e14c6a7 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -32,14 +32,15 @@ struct notifier_block br_device_notifier = {
32static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 32static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
33{ 33{
34 struct net_device *dev = ptr; 34 struct net_device *dev = ptr;
35 struct net_bridge_port *p = dev->br_port; 35 struct net_bridge_port *p = br_port_get(dev);
36 struct net_bridge *br; 36 struct net_bridge *br;
37 int err; 37 int err;
38 38
39 /* not a port of a bridge */ 39 /* not a port of a bridge */
40 if (p == NULL) 40 if (!br_port_exists(dev))
41 return NOTIFY_DONE; 41 return NOTIFY_DONE;
42 42
43 p = br_port_get(dev);
43 br = p->br; 44 br = p->br;
44 45
45 switch (event) { 46 switch (event) {
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 0f5394c4f2f1..f6bc979b1135 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -150,6 +150,11 @@ struct net_bridge_port
150#endif 150#endif
151}; 151};
152 152
153#define br_port_get_rcu(dev) \
154 ((struct net_bridge_port *) rcu_dereference(dev->rx_handler_data))
155#define br_port_get(dev) ((struct net_bridge_port *) dev->rx_handler_data)
156#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
157
153struct br_cpu_netstats { 158struct br_cpu_netstats {
154 unsigned long rx_packets; 159 unsigned long rx_packets;
155 unsigned long rx_bytes; 160 unsigned long rx_bytes;
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 217bd225a42f..70aecb48fb69 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -137,12 +137,13 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
137 struct net_device *dev) 137 struct net_device *dev)
138{ 138{
139 const unsigned char *dest = eth_hdr(skb)->h_dest; 139 const unsigned char *dest = eth_hdr(skb)->h_dest;
140 struct net_bridge_port *p = rcu_dereference(dev->br_port); 140 struct net_bridge_port *p;
141 struct net_bridge *br; 141 struct net_bridge *br;
142 const unsigned char *buf; 142 const unsigned char *buf;
143 143
144 if (!p) 144 if (!br_port_exists(dev))
145 goto err; 145 goto err;
146 p = br_port_get_rcu(dev);
146 147
147 if (!pskb_may_pull(skb, 4)) 148 if (!pskb_may_pull(skb, 4))
148 goto err; 149 goto err;
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 9e19166ba453..46624bb6d9be 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -24,8 +24,9 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
24 return EBT_DROP; 24 return EBT_DROP;
25 25
26 if (par->hooknum != NF_BR_BROUTING) 26 if (par->hooknum != NF_BR_BROUTING)
27 /* rcu_read_lock()ed by nf_hook_slow */
27 memcpy(eth_hdr(skb)->h_dest, 28 memcpy(eth_hdr(skb)->h_dest,
28 par->in->br_port->br->dev->dev_addr, ETH_ALEN); 29 br_port_get_rcu(par->in)->br->dev->dev_addr, ETH_ALEN);
29 else 30 else
30 memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN); 31 memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN);
31 skb->pkt_type = PACKET_HOST; 32 skb->pkt_type = PACKET_HOST;
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index ae3c7cef1484..26377e96fa1c 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -177,8 +177,9 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
177 if (in) { 177 if (in) {
178 strcpy(pm->physindev, in->name); 178 strcpy(pm->physindev, in->name);
179 /* If in isn't a bridge, then physindev==indev */ 179 /* If in isn't a bridge, then physindev==indev */
180 if (in->br_port) 180 if (br_port_exists(in))
181 strcpy(pm->indev, in->br_port->br->dev->name); 181 /* rcu_read_lock()ed by nf_hook_slow */
182 strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
182 else 183 else
183 strcpy(pm->indev, in->name); 184 strcpy(pm->indev, in->name);
184 } else 185 } else
@@ -187,7 +188,8 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
187 if (out) { 188 if (out) {
188 /* If out exists, then out is a bridge port */ 189 /* If out exists, then out is a bridge port */
189 strcpy(pm->physoutdev, out->name); 190 strcpy(pm->physoutdev, out->name);
190 strcpy(pm->outdev, out->br_port->br->dev->name); 191 /* rcu_read_lock()ed by nf_hook_slow */
192 strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
191 } else 193 } else
192 pm->outdev[0] = pm->physoutdev[0] = '\0'; 194 pm->outdev[0] = pm->physoutdev[0] = '\0';
193 195
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 59ca00e40dec..bcc102e3be4d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -140,11 +140,14 @@ ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
140 return 1; 140 return 1;
141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT)) 141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
142 return 1; 142 return 1;
143 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check( 143 /* rcu_read_lock()ed by nf_hook_slow */
144 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN)) 144 if (in && br_port_exists(in) &&
145 FWINV2(ebt_dev_check(e->logical_in, br_port_get_rcu(in)->br->dev),
146 EBT_ILOGICALIN))
145 return 1; 147 return 1;
146 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check( 148 if (out && br_port_exists(out) &&
147 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT)) 149 FWINV2(ebt_dev_check(e->logical_out, br_port_get_rcu(out)->br->dev),
150 EBT_ILOGICALOUT))
148 return 1; 151 return 1;
149 152
150 if (e->bitmask & EBT_SOURCEMAC) { 153 if (e->bitmask & EBT_SOURCEMAC) {
diff --git a/net/core/dev.c b/net/core/dev.c
index abdb19e547a7..5902426ef585 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2765,7 +2765,8 @@ int __skb_bond_should_drop(struct sk_buff *skb, struct net_device *master)
2765 if (master->priv_flags & IFF_MASTER_ARPMON) 2765 if (master->priv_flags & IFF_MASTER_ARPMON)
2766 dev->last_rx = jiffies; 2766 dev->last_rx = jiffies;
2767 2767
2768 if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) { 2768 if ((master->priv_flags & IFF_MASTER_ALB) &&
2769 (master->priv_flags & IFF_BRIDGE_PORT)) {
2769 /* Do address unmangle. The local destination address 2770 /* Do address unmangle. The local destination address
2770 * will be always the one master has. Provides the right 2771 * will be always the one master has. Provides the right
2771 * functionality in a bridge. 2772 * functionality in a bridge.
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index fc9a211e629e..e0504e90a0f0 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -403,8 +403,9 @@ __build_packet_message(struct nfulnl_instance *inst,
403 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, 403 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
404 htonl(indev->ifindex)); 404 htonl(indev->ifindex));
405 /* this is the bridge group "brX" */ 405 /* this is the bridge group "brX" */
406 /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
406 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, 407 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
407 htonl(indev->br_port->br->dev->ifindex)); 408 htonl(br_port_get_rcu(indev)->br->dev->ifindex));
408 } else { 409 } else {
409 /* Case 2: indev is bridge group, we need to look for 410 /* Case 2: indev is bridge group, we need to look for
410 * physical device (when called from ipv4) */ 411 * physical device (when called from ipv4) */
@@ -430,8 +431,9 @@ __build_packet_message(struct nfulnl_instance *inst,
430 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, 431 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
431 htonl(outdev->ifindex)); 432 htonl(outdev->ifindex));
432 /* this is the bridge group "brX" */ 433 /* this is the bridge group "brX" */
434 /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
433 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, 435 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
434 htonl(outdev->br_port->br->dev->ifindex)); 436 htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
435 } else { 437 } else {
436 /* Case 2: indev is a bridge group, we need to look 438 /* Case 2: indev is a bridge group, we need to look
437 * for physical device (when called from ipv4) */ 439 * for physical device (when called from ipv4) */
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 12e1ab37fcd8..cc3ae861e8f3 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -296,8 +296,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
296 NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV, 296 NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
297 htonl(indev->ifindex)); 297 htonl(indev->ifindex));
298 /* this is the bridge group "brX" */ 298 /* this is the bridge group "brX" */
299 /* rcu_read_lock()ed by __nf_queue */
299 NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, 300 NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
300 htonl(indev->br_port->br->dev->ifindex)); 301 htonl(br_port_get_rcu(indev)->br->dev->ifindex));
301 } else { 302 } else {
302 /* Case 2: indev is bridge group, we need to look for 303 /* Case 2: indev is bridge group, we need to look for
303 * physical device (when called from ipv4) */ 304 * physical device (when called from ipv4) */
@@ -321,8 +322,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
321 NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV, 322 NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
322 htonl(outdev->ifindex)); 323 htonl(outdev->ifindex));
323 /* this is the bridge group "brX" */ 324 /* this is the bridge group "brX" */
325 /* rcu_read_lock()ed by __nf_queue */
324 NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, 326 NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
325 htonl(outdev->br_port->br->dev->ifindex)); 327 htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
326 } else { 328 } else {
327 /* Case 2: outdev is bridge group, we need to look for 329 /* Case 2: outdev is bridge group, we need to look for
328 * physical output device (when called from ipv4) */ 330 * physical output device (when called from ipv4) */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90ab3c8519be..3a7b8a2f2d5a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1107,7 +1107,7 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
1107 enum nl80211_iftype iftype) 1107 enum nl80211_iftype iftype)
1108{ 1108{
1109 if (!use_4addr) { 1109 if (!use_4addr) {
1110 if (netdev && netdev->br_port) 1110 if (netdev && (netdev->priv_flags & IFF_BRIDGE_PORT))
1111 return -EBUSY; 1111 return -EBUSY;
1112 return 0; 1112 return 0;
1113 } 1113 }
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 3416373a9c0c..0c8a1e8b7690 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -770,8 +770,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
770 return -EOPNOTSUPP; 770 return -EOPNOTSUPP;
771 771
772 /* if it's part of a bridge, reject changing type to station/ibss */ 772 /* if it's part of a bridge, reject changing type to station/ibss */
773 if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC || 773 if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
774 ntype == NL80211_IFTYPE_STATION)) 774 (ntype == NL80211_IFTYPE_ADHOC || ntype == NL80211_IFTYPE_STATION))
775 return -EBUSY; 775 return -EBUSY;
776 776
777 if (ntype != otype) { 777 if (ntype != otype) {