commit 042a53a9e437feaf2230dd2cadcecfae9c7bfe05 Author: Eric Dumazet Date: Fri Jun 5 04:04:16 2009 +0000 net: skb_shared_info optimization skb_dma_unmap() is quite expensive for small packets, because we use two different cache lines from skb_shared_info. One to access nr_frags, one to access dma_maps[0] Instead of dma_maps being an array of MAX_SKB_FRAGS + 1 elements, let dma_head alone in a new dma_head field, close to nr_frags, to reduce cache lines misses. Tested on my dev machine (bnx2 & tg3 adapters), nice speedup ! Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Index: hurd-debian/libdde-linux26/contrib/include/linux/skbuff.h =================================================================== --- hurd-debian.orig/libdde-linux26/contrib/include/linux/skbuff.h 2012-04-16 00:26:40.000000000 +0000 +++ hurd-debian/libdde-linux26/contrib/include/linux/skbuff.h 2012-04-16 00:34:56.000000000 +0000 @@ -142,6 +142,9 @@ atomic_t dataref; unsigned short nr_frags; unsigned short gso_size; +#ifdef CONFIG_HAS_DMA + dma_addr_t dma_head; +#endif /* Warning: this field is not always filled in (UFO)! */ unsigned short gso_segs; unsigned short gso_type; @@ -152,7 +155,7 @@ struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; #ifdef CONFIG_HAS_DMA - dma_addr_t dma_maps[MAX_SKB_FRAGS + 1]; + dma_addr_t dma_maps[MAX_SKB_FRAGS]; #endif }; Index: hurd-debian/libdde-linux26/contrib/net/core/skb_dma_map.c =================================================================== --- hurd-debian.orig/libdde-linux26/contrib/net/core/skb_dma_map.c 2012-04-16 00:26:40.000000000 +0000 +++ hurd-debian/libdde-linux26/contrib/net/core/skb_dma_map.c 2012-04-16 00:34:56.000000000 +0000 @@ -20,7 +20,7 @@ if (dma_mapping_error(dev, map)) goto out_err; - sp->dma_maps[0] = map; + sp->dma_head = map; for (i = 0; i < sp->nr_frags; i++) { skb_frag_t *fp = &sp->frags[i]; @@ -28,7 +28,7 @@ fp->size, dir); if (dma_mapping_error(dev, map)) goto unwind; - sp->dma_maps[i + 1] = map; + sp->dma_maps[i] = map; } sp->num_dma_maps = i + 1; @@ -38,10 +38,10 @@ while (--i >= 0) { skb_frag_t *fp = &sp->frags[i]; - dma_unmap_page(dev, sp->dma_maps[i + 1], + dma_unmap_page(dev, sp->dma_maps[i], fp->size, dir); } - dma_unmap_single(dev, sp->dma_maps[0], + dma_unmap_single(dev, sp->dma_head, skb_headlen(skb), dir); out_err: return -ENOMEM; @@ -54,12 +54,12 @@ struct skb_shared_info *sp = skb_shinfo(skb); int i; - dma_unmap_single(dev, sp->dma_maps[0], + dma_unmap_single(dev, sp->dma_head, skb_headlen(skb), dir); for (i = 0; i < sp->nr_frags; i++) { skb_frag_t *fp = &sp->frags[i]; - dma_unmap_page(dev, sp->dma_maps[i + 1], + dma_unmap_page(dev, sp->dma_maps[i], fp->size, dir); } }