2 * Simple allocator for internal RAM in ETRAX FS
4 * Copyright (c) 2004 Axis Communications AB.
7 #include <linux/list.h>
8 #include <linux/slab.h>
13 #define STATUS_ALLOCATED 1
15 #ifdef CONFIG_ETRAX_L2CACHE
16 #define RESERVED_SIZE 66*1024
18 #define RESERVED_SIZE 0
21 struct intmem_allocation
{
22 struct list_head entry
;
29 static struct list_head intmem_allocations
;
30 static void* intmem_virtual
;
32 static void crisv32_intmem_init(void)
34 static int initiated
= 0;
36 struct intmem_allocation
* alloc
;
37 alloc
= kmalloc(sizeof *alloc
, GFP_KERNEL
);
38 INIT_LIST_HEAD(&intmem_allocations
);
39 intmem_virtual
= ioremap(MEM_INTMEM_START
+ RESERVED_SIZE
,
40 MEM_INTMEM_SIZE
- RESERVED_SIZE
);
42 alloc
->size
= MEM_INTMEM_SIZE
- RESERVED_SIZE
;
44 alloc
->status
= STATUS_FREE
;
45 list_add_tail(&alloc
->entry
, &intmem_allocations
);
49 void* crisv32_intmem_alloc(unsigned size
, unsigned align
)
51 struct intmem_allocation
* allocation
;
52 struct intmem_allocation
* tmp
;
56 crisv32_intmem_init();
58 list_for_each_entry_safe(allocation
, tmp
, &intmem_allocations
, entry
) {
59 int alignment
= allocation
->offset
% align
;
60 alignment
= alignment
? align
- alignment
: alignment
;
62 if (allocation
->status
== STATUS_FREE
&&
63 allocation
->size
>= size
+ alignment
) {
64 if (allocation
->size
> size
+ alignment
) {
65 struct intmem_allocation
* alloc
;
66 alloc
= kmalloc(sizeof *alloc
, GFP_ATOMIC
);
67 alloc
->status
= STATUS_FREE
;
68 alloc
->size
= allocation
->size
- size
-
70 alloc
->offset
= allocation
->offset
+ size
+
72 list_add(&alloc
->entry
, &allocation
->entry
);
75 struct intmem_allocation
*tmp
;
76 tmp
= kmalloc(sizeof *tmp
, GFP_ATOMIC
);
77 tmp
->offset
= allocation
->offset
;
78 tmp
->size
= alignment
;
79 tmp
->status
= STATUS_FREE
;
80 allocation
->offset
+= alignment
;
81 list_add_tail(&tmp
->entry
,
85 allocation
->status
= STATUS_ALLOCATED
;
86 allocation
->size
= size
;
87 ret
= (void*)((int)intmem_virtual
+ allocation
->offset
);
94 void crisv32_intmem_free(void* addr
)
96 struct intmem_allocation
* allocation
;
97 struct intmem_allocation
* tmp
;
103 crisv32_intmem_init();
105 list_for_each_entry_safe(allocation
, tmp
, &intmem_allocations
, entry
) {
106 if (allocation
->offset
== (int)(addr
- intmem_virtual
)) {
107 struct intmem_allocation
*prev
=
108 list_entry(allocation
->entry
.prev
,
109 struct intmem_allocation
, entry
);
110 struct intmem_allocation
*next
=
111 list_entry(allocation
->entry
.next
,
112 struct intmem_allocation
, entry
);
114 allocation
->status
= STATUS_FREE
;
115 /* Join with prev and/or next if also free */
116 if ((prev
!= &intmem_allocations
) &&
117 (prev
->status
== STATUS_FREE
)) {
118 prev
->size
+= allocation
->size
;
119 list_del(&allocation
->entry
);
123 if ((next
!= &intmem_allocations
) &&
124 (next
->status
== STATUS_FREE
)) {
125 allocation
->size
+= next
->size
;
126 list_del(&next
->entry
);
136 void* crisv32_intmem_phys_to_virt(unsigned long addr
)
138 return (void *)(addr
- (MEM_INTMEM_START
+ RESERVED_SIZE
) +
139 (unsigned long)intmem_virtual
);
142 unsigned long crisv32_intmem_virt_to_phys(void* addr
)
144 return (unsigned long)((unsigned long )addr
-
145 (unsigned long)intmem_virtual
+ MEM_INTMEM_START
+
148 device_initcall(crisv32_intmem_init
);