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>
10 #include <asm/arch/memmap.h>
13 #define STATUS_ALLOCATED 1
15 struct intmem_allocation
{
16 struct list_head entry
;
23 static struct list_head intmem_allocations
;
24 static void* intmem_virtual
;
26 static void crisv32_intmem_init(void)
28 static int initiated
= 0;
30 struct intmem_allocation
* alloc
=
31 (struct intmem_allocation
*)kmalloc(sizeof *alloc
, GFP_KERNEL
);
32 INIT_LIST_HEAD(&intmem_allocations
);
33 intmem_virtual
= ioremap(MEM_INTMEM_START
, MEM_INTMEM_SIZE
);
35 alloc
->size
= MEM_INTMEM_SIZE
;
37 alloc
->status
= STATUS_FREE
;
38 list_add_tail(&alloc
->entry
, &intmem_allocations
);
42 void* crisv32_intmem_alloc(unsigned size
, unsigned align
)
44 struct intmem_allocation
* allocation
;
45 struct intmem_allocation
* tmp
;
49 crisv32_intmem_init();
51 list_for_each_entry_safe(allocation
, tmp
, &intmem_allocations
, entry
) {
52 int alignment
= allocation
->offset
% align
;
53 alignment
= alignment
? align
- alignment
: alignment
;
55 if (allocation
->status
== STATUS_FREE
&&
56 allocation
->size
>= size
+ alignment
) {
57 if (allocation
->size
> size
+ alignment
) {
58 struct intmem_allocation
* alloc
=
59 (struct intmem_allocation
*)
60 kmalloc(sizeof *alloc
, GFP_ATOMIC
);
61 alloc
->status
= STATUS_FREE
;
62 alloc
->size
= allocation
->size
- size
- alignment
;
63 alloc
->offset
= allocation
->offset
+ size
;
64 list_add(&alloc
->entry
, &allocation
->entry
);
67 struct intmem_allocation
* tmp
;
68 tmp
= (struct intmem_allocation
*)
69 kmalloc(sizeof *tmp
, GFP_ATOMIC
);
70 tmp
->offset
= allocation
->offset
;
71 tmp
->size
= alignment
;
72 tmp
->status
= STATUS_FREE
;
73 allocation
->offset
+= alignment
;
74 list_add_tail(&tmp
->entry
, &allocation
->entry
);
77 allocation
->status
= STATUS_ALLOCATED
;
78 allocation
->size
= size
;
79 ret
= (void*)((int)intmem_virtual
+ allocation
->offset
);
86 void crisv32_intmem_free(void* addr
)
88 struct intmem_allocation
* allocation
;
89 struct intmem_allocation
* tmp
;
95 crisv32_intmem_init();
97 list_for_each_entry_safe(allocation
, tmp
, &intmem_allocations
, entry
) {
98 if (allocation
->offset
== (int)(addr
- intmem_virtual
)) {
99 struct intmem_allocation
* prev
=
100 list_entry(allocation
->entry
.prev
,
101 struct intmem_allocation
, entry
);
102 struct intmem_allocation
* next
=
103 list_entry(allocation
->entry
.next
,
104 struct intmem_allocation
, entry
);
106 allocation
->status
= STATUS_FREE
;
107 /* Join with prev and/or next if also free */
108 if (prev
->status
== STATUS_FREE
) {
109 prev
->size
+= allocation
->size
;
110 list_del(&allocation
->entry
);
114 if (next
->status
== STATUS_FREE
) {
115 allocation
->size
+= next
->size
;
116 list_del(&next
->entry
);
126 void* crisv32_intmem_phys_to_virt(unsigned long addr
)
128 return (void*)(addr
- MEM_INTMEM_START
+
129 (unsigned long)intmem_virtual
);
132 unsigned long crisv32_intmem_virt_to_phys(void* addr
)
134 return (unsigned long)((unsigned long )addr
-
135 (unsigned long)intmem_virtual
+ MEM_INTMEM_START
);