ibmveth: Add rx_copybreak
authorSantiago Leon <santil@linux.vnet.ibm.com>
Fri, 3 Sep 2010 18:28:25 +0000 (18:28 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Sep 2010 01:20:34 +0000 (18:20 -0700)
For small packets, create a new skb and copy the packet into it so we
avoid tearing down and creating a TCE entry.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Santiago Leon <santil@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ibmveth.c

index fc6e2cf879c0a32a48496096bab8acd5a966184b..c236c8af33673482eb5a0a6b814df7bd84274b71 100644 (file)
@@ -122,6 +122,11 @@ module_param(tx_copybreak, uint, 0644);
 MODULE_PARM_DESC(tx_copybreak,
        "Maximum size of packet that is copied to a new buffer on transmit");
 
+static unsigned int rx_copybreak __read_mostly = 128;
+module_param(rx_copybreak, uint, 0644);
+MODULE_PARM_DESC(rx_copybreak,
+       "Maximum size of packet that is copied to a new buffer on receive");
+
 struct ibmveth_stat {
        char name[ETH_GSTRING_LEN];
        int offset;
@@ -1002,8 +1007,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
 
  restart_poll:
        do {
-               struct sk_buff *skb;
-
                if (!ibmveth_rxq_pending_buffer(adapter))
                        break;
 
@@ -1014,20 +1017,34 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
                        ibmveth_debug_printk("recycling invalid buffer\n");
                        ibmveth_rxq_recycle_buffer(adapter);
                } else {
+                       struct sk_buff *skb, *new_skb;
                        int length = ibmveth_rxq_frame_length(adapter);
                        int offset = ibmveth_rxq_frame_offset(adapter);
                        int csum_good = ibmveth_rxq_csum_good(adapter);
 
                        skb = ibmveth_rxq_get_buffer(adapter);
-                       if (csum_good)
-                               skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-                       ibmveth_rxq_harvest_buffer(adapter);
+                       new_skb = NULL;
+                       if (length < rx_copybreak)
+                               new_skb = netdev_alloc_skb(netdev, length);
+
+                       if (new_skb) {
+                               skb_copy_to_linear_data(new_skb,
+                                                       skb->data + offset,
+                                                       length);
+                               skb = new_skb;
+                               ibmveth_rxq_recycle_buffer(adapter);
+                       } else {
+                               ibmveth_rxq_harvest_buffer(adapter);
+                               skb_reserve(skb, offset);
+                       }
 
-                       skb_reserve(skb, offset);
                        skb_put(skb, length);
                        skb->protocol = eth_type_trans(skb, netdev);
 
+                       if (csum_good)
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
+
                        netif_receive_skb(skb); /* send it up */
 
                        netdev->stats.rx_packets++;