ia64/xen-unstable

changeset 6235:7bd1a40ae2bd

Fix the skbuff allocator for multi-page buffers.
pci-dma.c still needs fixing to recognise contiguous
multi-page buffers.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Aug 17 16:53:30 2005 +0000 (2005-08-17)
parents d4f6247b2a1b
children c63e764da785
files linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c	Wed Aug 17 15:34:58 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c	Wed Aug 17 16:53:30 2005 +0000
     1.3 @@ -5,8 +5,6 @@
     1.4  #include <linux/kernel.h>
     1.5  #include <linux/sched.h>
     1.6  #include <linux/slab.h>
     1.7 -#include <linux/string.h>
     1.8 -#include <linux/errno.h>
     1.9  #include <linux/netdevice.h>
    1.10  #include <linux/inetdevice.h>
    1.11  #include <linux/etherdevice.h>
    1.12 @@ -14,34 +12,86 @@
    1.13  #include <linux/init.h>
    1.14  #include <asm/io.h>
    1.15  #include <asm/page.h>
    1.16 -
    1.17 -EXPORT_SYMBOL(__dev_alloc_skb);
    1.18 +#include <asm-xen/hypervisor.h>
    1.19  
    1.20  /* Referenced in netback.c. */
    1.21  /*static*/ kmem_cache_t *skbuff_cachep;
    1.22  
    1.23 -/* Size must be cacheline-aligned (alloc_skb uses SKB_DATA_ALIGN). */
    1.24 -#define XEN_SKB_SIZE \
    1.25 -    ((PAGE_SIZE - sizeof(struct skb_shared_info)) & ~(SMP_CACHE_BYTES - 1))
    1.26 +#define MAX_SKBUFF_ORDER 2
    1.27 +static kmem_cache_t *skbuff_order_cachep[MAX_SKBUFF_ORDER + 1];
    1.28  
    1.29  struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask)
    1.30  {
    1.31 -    struct sk_buff *skb;
    1.32 -    skb = alloc_skb_from_cache(skbuff_cachep, length + 16, gfp_mask);
    1.33 -    if ( likely(skb != NULL) )
    1.34 -        skb_reserve(skb, 16);
    1.35 -    return skb;
    1.36 +	struct sk_buff *skb;
    1.37 +	int order;
    1.38 +
    1.39 +	length = SKB_DATA_ALIGN(length + 16);
    1.40 +	order = get_order(length + sizeof(struct skb_shared_info));
    1.41 +	if (order > MAX_SKBUFF_ORDER) {
    1.42 +		printk(KERN_ALERT "Attempt to allocate order %d skbuff. "
    1.43 +		       "Increase MAX_SKBUFF_ORDER.\n", order);
    1.44 +		return NULL;
    1.45 +	}
    1.46 +
    1.47 +	skb = alloc_skb_from_cache(
    1.48 +		skbuff_order_cachep[order], length, gfp_mask);
    1.49 +	if (skb != NULL)
    1.50 +		skb_reserve(skb, 16);
    1.51 +
    1.52 +	return skb;
    1.53  }
    1.54  
    1.55  static void skbuff_ctor(void *buf, kmem_cache_t *cachep, unsigned long unused)
    1.56  {
    1.57 -    scrub_pages(buf, 1);
    1.58 +	int order = 0;
    1.59 +
    1.60 +	while (skbuff_order_cachep[order] != cachep)
    1.61 +		order++;
    1.62 +
    1.63 +	if (order != 0)
    1.64 +		xen_create_contiguous_region((unsigned long)buf, order);
    1.65 +
    1.66 +	scrub_pages(buf, 1 << order);
    1.67 +}
    1.68 +
    1.69 +static void skbuff_dtor(void *buf, kmem_cache_t *cachep, unsigned long unused)
    1.70 +{
    1.71 +	int order = 0;
    1.72 +
    1.73 +	while (skbuff_order_cachep[order] != cachep)
    1.74 +		order++;
    1.75 +
    1.76 +	if (order != 0)
    1.77 +		xen_destroy_contiguous_region((unsigned long)buf, order);
    1.78  }
    1.79  
    1.80  static int __init skbuff_init(void)
    1.81  {
    1.82 -    skbuff_cachep = kmem_cache_create(
    1.83 -        "xen-skb", PAGE_SIZE, PAGE_SIZE, 0, skbuff_ctor, NULL);
    1.84 -    return 0;
    1.85 +	static char name[MAX_SKBUFF_ORDER + 1][20];
    1.86 +	unsigned long size;
    1.87 +	int order;
    1.88 +
    1.89 +	for (order = 0; order <= MAX_SKBUFF_ORDER; order++) {
    1.90 +		size = PAGE_SIZE << order;
    1.91 +		sprintf(name[order], "xen-skb-%lu", size);
    1.92 +		skbuff_order_cachep[order] = kmem_cache_create(
    1.93 +			name[order], size, size, 0, skbuff_ctor, skbuff_dtor);
    1.94 +	}
    1.95 +
    1.96 +	skbuff_cachep = skbuff_order_cachep[0];
    1.97 +
    1.98 +	return 0;
    1.99  }
   1.100  __initcall(skbuff_init);
   1.101 +
   1.102 +EXPORT_SYMBOL(__dev_alloc_skb);
   1.103 +
   1.104 +/*
   1.105 + * Local variables:
   1.106 + *  c-file-style: "linux"
   1.107 + *  indent-tabs-mode: t
   1.108 + *  c-indent-level: 8
   1.109 + *  c-basic-offset: 8
   1.110 + *  tab-width: 8
   1.111 + * End:
   1.112 + */