2 * This file is based on code from OCTEON SDK by Cavium Networks.
4 * Copyright (c) 2003-2010 Cavium Networks
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, Version 2, as
8 * published by the Free Software Foundation.
11 #include <linux/kernel.h>
12 #include <linux/netdevice.h>
13 #include <linux/slab.h>
15 #include <asm/octeon/octeon.h>
17 #include "ethernet-mem.h"
18 #include "ethernet-defines.h"
20 #include <asm/octeon/cvmx-fpa.h>
23 * cvm_oct_fill_hw_skbuff - fill the supplied hardware pool with skbuffs
24 * @pool: Pool to allocate an skbuff for
25 * @size: Size of the buffer needed for the pool
26 * @elements: Number of buffers to allocate
28 * Returns the actual number of buffers allocated.
30 static int cvm_oct_fill_hw_skbuff(int pool
, int size
, int elements
)
35 struct sk_buff
*skb
= dev_alloc_skb(size
+ 256);
37 if (unlikely(skb
== NULL
))
39 skb_reserve(skb
, 256 - (((unsigned long)skb
->data
) & 0x7f));
40 *(struct sk_buff
**)(skb
->data
- sizeof(void *)) = skb
;
41 cvmx_fpa_free(skb
->data
, pool
, size
/ 128);
44 return elements
- freed
;
48 * cvm_oct_free_hw_skbuff- free hardware pool skbuffs
49 * @pool: Pool to allocate an skbuff for
50 * @size: Size of the buffer needed for the pool
51 * @elements: Number of buffers to allocate
53 static void cvm_oct_free_hw_skbuff(int pool
, int size
, int elements
)
58 memory
= cvmx_fpa_alloc(pool
);
61 *(struct sk_buff
**)(memory
- sizeof(void *));
68 pr_warn("Freeing of pool %u had too many skbuffs (%d)\n",
70 else if (elements
> 0)
71 pr_warn("Freeing of pool %u is missing %d skbuffs\n",
76 * cvm_oct_fill_hw_memory - fill a hardware pool with memory.
77 * @pool: Pool to populate
78 * @size: Size of each buffer in the pool
79 * @elements: Number of buffers to allocate
81 * Returns the actual number of buffers allocated.
83 static int cvm_oct_fill_hw_memory(int pool
, int size
, int elements
)
91 * FPA memory must be 128 byte aligned. Since we are
92 * aligning we need to save the original pointer so we
93 * can feed it to kfree when the memory is returned to
96 * We allocate an extra 256 bytes to allow for
97 * alignment and space for the original pointer saved
98 * just before the block.
100 memory
= kmalloc(size
+ 256, GFP_ATOMIC
);
101 if (unlikely(memory
== NULL
)) {
102 pr_warn("Unable to allocate %u bytes for FPA pool %d\n",
103 elements
* size
, pool
);
106 fpa
= (char *)(((unsigned long)memory
+ 256) & ~0x7fUL
);
107 *((char **)fpa
- 1) = memory
;
108 cvmx_fpa_free(fpa
, pool
, 0);
111 return elements
- freed
;
115 * cvm_oct_free_hw_memory - Free memory allocated by cvm_oct_fill_hw_memory
116 * @pool: FPA pool to free
117 * @size: Size of each buffer in the pool
118 * @elements: Number of buffers that should be in the pool
120 static void cvm_oct_free_hw_memory(int pool
, int size
, int elements
)
126 fpa
= cvmx_fpa_alloc(pool
);
129 fpa
= (char *)phys_to_virt(cvmx_ptr_to_phys(fpa
));
130 memory
= *((char **)fpa
- 1);
136 pr_warn("Freeing of pool %u had too many buffers (%d)\n",
138 else if (elements
> 0)
139 pr_warn("Warning: Freeing of pool %u is missing %d buffers\n",
143 int cvm_oct_mem_fill_fpa(int pool
, int size
, int elements
)
147 if (pool
== CVMX_FPA_PACKET_POOL
)
148 freed
= cvm_oct_fill_hw_skbuff(pool
, size
, elements
);
150 freed
= cvm_oct_fill_hw_memory(pool
, size
, elements
);
154 void cvm_oct_mem_empty_fpa(int pool
, int size
, int elements
)
156 if (pool
== CVMX_FPA_PACKET_POOL
)
157 cvm_oct_free_hw_skbuff(pool
, size
, elements
);
159 cvm_oct_free_hw_memory(pool
, size
, elements
);