Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / bridge / br_device.c
index 3334845376005cdba3a3b6b2d0b4013da4617446..070e8a68cfc63f856b281b4f19e08181cbd5172f 100644 (file)
@@ -31,9 +31,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        struct net_bridge_mdb_entry *mdst;
        struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
 
+       rcu_read_lock();
 #ifdef CONFIG_BRIDGE_NETFILTER
        if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) {
                br_nf_pre_routing_finish_bridge_slow(skb);
+               rcu_read_unlock();
                return NETDEV_TX_OK;
        }
 #endif
@@ -48,7 +50,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        skb_reset_mac_header(skb);
        skb_pull(skb, ETH_HLEN);
 
-       rcu_read_lock();
        if (is_broadcast_ether_addr(dest))
                br_flood_deliver(br, skb);
        else if (is_multicast_ether_addr(dest)) {
@@ -206,24 +207,23 @@ static void br_poll_controller(struct net_device *br_dev)
 static void br_netpoll_cleanup(struct net_device *dev)
 {
        struct net_bridge *br = netdev_priv(dev);
-       struct net_bridge_port *p, *n;
+       struct net_bridge_port *p;
 
-       list_for_each_entry_safe(p, n, &br->port_list, list) {
+       list_for_each_entry(p, &br->port_list, list)
                br_netpoll_disable(p);
-       }
 }
 
-static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
+static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
+                           gfp_t gfp)
 {
        struct net_bridge *br = netdev_priv(dev);
-       struct net_bridge_port *p, *n;
+       struct net_bridge_port *p;
        int err = 0;
 
-       list_for_each_entry_safe(p, n, &br->port_list, list) {
+       list_for_each_entry(p, &br->port_list, list) {
                if (!p->dev)
                        continue;
-
-               err = br_netpoll_enable(p);
+               err = br_netpoll_enable(p, gfp);
                if (err)
                        goto fail;
        }
@@ -236,17 +236,17 @@ fail:
        goto out;
 }
 
-int br_netpoll_enable(struct net_bridge_port *p)
+int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
 {
        struct netpoll *np;
        int err = 0;
 
-       np = kzalloc(sizeof(*p->np), GFP_KERNEL);
+       np = kzalloc(sizeof(*p->np), gfp);
        err = -ENOMEM;
        if (!np)
                goto out;
 
-       err = __netpoll_setup(np, p->dev);
+       err = __netpoll_setup(np, p->dev, gfp);
        if (err) {
                kfree(np);
                goto out;
@@ -267,11 +267,7 @@ void br_netpoll_disable(struct net_bridge_port *p)
 
        p->np = NULL;
 
-       /* Wait for transmitting packets to finish before freeing. */
-       synchronize_rcu_bh();
-
-       __netpoll_cleanup(np);
-       kfree(np);
+       __netpoll_free_rcu(np);
 }
 
 #endif