]> git.hungrycats.org Git - linux/commitdiff
[NET]: Do less atomic count changes in dev_queue_xmit.
authorAndi Kleen <ak@suse.de>
Tue, 7 Sep 2004 06:36:36 +0000 (23:36 -0700)
committerPatrick McHardy <kaber@trash.net>
Tue, 7 Sep 2004 06:36:36 +0000 (23:36 -0700)
With suggestions from Herbert Xu

Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/dev.c

index 7a50c543e5057d4f31c3d84a19f1a12253dc9943..47b3d8497a5dda01d636073882ff2490fe5f055b 100644 (file)
@@ -1249,17 +1249,17 @@ int __skb_linearize(struct sk_buff *skb, int gfp_mask)
        return 0;
 }
 
-#define HARD_TX_LOCK_BH(dev, cpu) {                    \
+#define HARD_TX_LOCK(dev, cpu) {                       \
        if ((dev->features & NETIF_F_LLTX) == 0) {      \
-               spin_lock_bh(&dev->xmit_lock);          \
+               spin_lock(&dev->xmit_lock);             \
                dev->xmit_lock_owner = cpu;             \
        }                                               \
 }
 
-#define HARD_TX_UNLOCK_BH(dev) {                       \
+#define HARD_TX_UNLOCK(dev) {                          \
        if ((dev->features & NETIF_F_LLTX) == 0) {      \
                dev->xmit_lock_owner = -1;              \
-               spin_unlock_bh(&dev->xmit_lock);        \
+               spin_unlock(&dev->xmit_lock);           \
        }                                               \
 }
 
@@ -1313,7 +1313,12 @@ int dev_queue_xmit(struct sk_buff *skb)
                if (skb_checksum_help(&skb, 0))
                        goto out_kfree_skb;
 
-       rcu_read_lock();
+
+       /* Disable soft irqs for various locks below. Also 
+        * stops preemption for RCU. 
+        */
+       local_bh_disable(); 
+
        /* Updates of qdisc are serialized by queue_lock. 
         * The struct Qdisc which is pointed to by qdisc is now a 
         * rcu structure - it may be accessed without acquiring 
@@ -1332,18 +1337,16 @@ int dev_queue_xmit(struct sk_buff *skb)
 #endif
        if (q->enqueue) {
                /* Grab device queue */
-               spin_lock_bh(&dev->queue_lock);
+               spin_lock(&dev->queue_lock);
 
                rc = q->enqueue(skb, q);
 
                qdisc_run(dev);
 
-               spin_unlock_bh(&dev->queue_lock);
-               rcu_read_unlock();
+               spin_unlock(&dev->queue_lock);
                rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
                goto out;
        }
-       rcu_read_unlock();
 
        /* The device has no queue. Common case for software devices:
           loopback, all the sorts of tunnels...
@@ -1358,12 +1361,11 @@ int dev_queue_xmit(struct sk_buff *skb)
           Either shot noqueue qdisc, it is even simpler 8)
         */
        if (dev->flags & IFF_UP) {
-               int cpu = get_cpu();
+               int cpu = smp_processor_id(); /* ok because BHs are off */
 
                if (dev->xmit_lock_owner != cpu) {
 
-                       HARD_TX_LOCK_BH(dev, cpu);
-                       put_cpu();
+                       HARD_TX_LOCK(dev, cpu);
 
                        if (!netif_queue_stopped(dev)) {
                                if (netdev_nit)
@@ -1371,17 +1373,16 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                                rc = 0;
                                if (!dev->hard_start_xmit(skb, dev)) {
-                                       HARD_TX_UNLOCK_BH(dev);
+                                       HARD_TX_UNLOCK(dev);
                                        goto out;
                                }
                        }
-                       HARD_TX_UNLOCK_BH(dev);
+                       HARD_TX_UNLOCK(dev);
                        if (net_ratelimit())
                                printk(KERN_CRIT "Virtual device %s asks to "
                                       "queue packet!\n", dev->name);
                        goto out_enetdown;
                } else {
-                       put_cpu();
                        /* Recursion is detected! It is possible,
                         * unfortunately */
                        if (net_ratelimit())
@@ -1394,6 +1395,7 @@ out_enetdown:
 out_kfree_skb:
        kfree_skb(skb);
 out:
+       local_bh_enable();
        return rc;
 }