]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/skbuff.c
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6-omap-h63xx.git] / net / core / skbuff.c
index 476aa397850451555cd1e88661f38200b42a4fb7..3c23760c5827518769f14ea3eaaa8fefb1e73397 100644 (file)
 static kmem_cache_t *skbuff_head_cache __read_mostly;
 static kmem_cache_t *skbuff_fclone_cache __read_mostly;
 
-/*
- * lockdep: lock class key used by skb_queue_head_init():
- */
-struct lock_class_key skb_queue_lock_key;
-
-EXPORT_SYMBOL(skb_queue_lock_key);
-
 /*
  *     Keep out-of-line to prevent kernel bloat.
  *     __builtin_return_address is not used because it is not always
@@ -163,7 +156,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
 
        /* Get the DATA. Size must match skb_add_mtu(). */
        size = SKB_DATA_ALIGN(size);
-       data = ____kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
+       data = kmalloc_track_caller(size + sizeof(struct skb_shared_info),
+                       gfp_mask);
        if (!data)
                goto nodata;
 
@@ -256,6 +250,31 @@ nodata:
        goto out;
 }
 
+/**
+ *     __netdev_alloc_skb - allocate an skbuff for rx on a specific device
+ *     @dev: network device to receive on
+ *     @length: length to allocate
+ *     @gfp_mask: get_free_pages mask, passed to alloc_skb
+ *
+ *     Allocate a new &sk_buff and assign it a usage count of one. The
+ *     buffer has unspecified headroom built in. Users should allocate
+ *     the headroom they think they need without accounting for the
+ *     built in space. The built in space is used for optimisations.
+ *
+ *     %NULL is returned if there is no free memory.
+ */
+struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+               unsigned int length, gfp_t gfp_mask)
+{
+       struct sk_buff *skb;
+
+       skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
+       if (likely(skb)) {
+               skb_reserve(skb, NET_SKB_PAD);
+               skb->dev = dev;
+       }
+       return skb;
+}
 
 static void skb_drop_list(struct sk_buff **listp)
 {
@@ -846,7 +865,11 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
            unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
                return err;
 
-       for (i = 0; i < nfrags; i++) {
+       i = 0;
+       if (offset >= len)
+               goto drop_pages;
+
+       for (; i < nfrags; i++) {
                int end = offset + skb_shinfo(skb)->frags[i].size;
 
                if (end < len) {
@@ -854,9 +877,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
                        continue;
                }
 
-               if (len > offset)
-                       skb_shinfo(skb)->frags[i++].size = len - offset;
+               skb_shinfo(skb)->frags[i++].size = len - offset;
 
+drop_pages:
                skb_shinfo(skb)->nr_frags = i;
 
                for (; i < nfrags; i++)
@@ -864,7 +887,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
 
                if (skb_shinfo(skb)->frag_list)
                        skb_drop_fraglist(skb);
-               break;
+               goto done;
        }
 
        for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
@@ -879,6 +902,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
                                return -ENOMEM;
 
                        nfrag->next = frag->next;
+                       kfree_skb(frag);
                        frag = nfrag;
                        *fragp = frag;
                }
@@ -897,6 +921,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
                break;
        }
 
+done:
        if (len > skb_headlen(skb)) {
                skb->data_len -= skb->len - len;
                skb->len       = len;
@@ -1373,7 +1398,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
        unsigned int csum;
        long csstart;
 
-       if (skb->ip_summed == CHECKSUM_HW)
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
                csstart = skb->h.raw - skb->data;
        else
                csstart = skb_headlen(skb);
@@ -1387,7 +1412,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
                csum = skb_copy_and_csum_bits(skb, csstart, to + csstart,
                                              skb->len - csstart, 0);
 
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                long csstuff = csstart + skb->csum;
 
                *((unsigned short *)(to + csstuff)) = csum_fold(csum);
@@ -1874,10 +1899,10 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
  *     @len: length of data pulled
  *
  *     This function performs an skb_pull on the packet and updates
- *     update the CHECKSUM_HW checksum.  It should be used on receive
- *     path processing instead of skb_pull unless you know that the
- *     checksum difference is zero (e.g., a valid IP header) or you
- *     are setting ip_summed to CHECKSUM_NONE.
+ *     update the CHECKSUM_COMPLETE checksum.  It should be used on
+ *     receive path processing instead of skb_pull unless you know
+ *     that the checksum difference is zero (e.g., a valid IP header)
+ *     or you are setting ip_summed to CHECKSUM_NONE.
  */
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
 {
@@ -1970,7 +1995,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
                frag = skb_shinfo(nskb)->frags;
                k = 0;
 
-               nskb->ip_summed = CHECKSUM_HW;
+               nskb->ip_summed = CHECKSUM_PARTIAL;
                nskb->csum = skb->csum;
                memcpy(skb_put(nskb, hsize), skb->data + offset, hsize);
 
@@ -2022,19 +2047,14 @@ void __init skb_init(void)
        skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
                                              sizeof(struct sk_buff),
                                              0,
-                                             SLAB_HWCACHE_ALIGN,
+                                             SLAB_HWCACHE_ALIGN|SLAB_PANIC,
                                              NULL, NULL);
-       if (!skbuff_head_cache)
-               panic("cannot create skbuff cache");
-
        skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
                                                (2*sizeof(struct sk_buff)) +
                                                sizeof(atomic_t),
                                                0,
-                                               SLAB_HWCACHE_ALIGN,
+                                               SLAB_HWCACHE_ALIGN|SLAB_PANIC,
                                                NULL, NULL);
-       if (!skbuff_fclone_cache)
-               panic("cannot create skbuff cache");
 }
 
 EXPORT_SYMBOL(___pskb_trim);
@@ -2042,6 +2062,7 @@ EXPORT_SYMBOL(__kfree_skb);
 EXPORT_SYMBOL(kfree_skb);
 EXPORT_SYMBOL(__pskb_pull_tail);
 EXPORT_SYMBOL(__alloc_skb);
+EXPORT_SYMBOL(__netdev_alloc_skb);
 EXPORT_SYMBOL(pskb_copy);
 EXPORT_SYMBOL(pskb_expand_head);
 EXPORT_SYMBOL(skb_checksum);