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 (struct intmem_allocation
*)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 (struct intmem_allocation
*)
67 kmalloc(sizeof *alloc
, GFP_ATOMIC
);
68 alloc
->status
= STATUS_FREE
;
69 alloc
->size
= allocation
->size
- size
-
71 alloc
->offset
= allocation
->offset
+ size
+
73 list_add(&alloc
->entry
, &allocation
->entry
);
76 struct intmem_allocation
*tmp
;
77 tmp
= (struct intmem_allocation
*)
80 tmp
->offset
= allocation
->offset
;
81 tmp
->size
= alignment
;
82 tmp
->status
= STATUS_FREE
;
83 allocation
->offset
+= alignment
;
84 list_add_tail(&tmp
->entry
,
88 allocation
->status
= STATUS_ALLOCATED
;
89 allocation
->size
= size
;
90 ret
= (void*)((int)intmem_virtual
+ allocation
->offset
);
97 void crisv32_intmem_free(void* addr
)
99 struct intmem_allocation
* allocation
;
100 struct intmem_allocation
* tmp
;
106 crisv32_intmem_init();
108 list_for_each_entry_safe(allocation
, tmp
, &intmem_allocations
, entry
) {
109 if (allocation
->offset
== (int)(addr
- intmem_virtual
)) {
110 struct intmem_allocation
*prev
=
111 list_entry(allocation
->entry
.prev
,
112 struct intmem_allocation
, entry
);
113 struct intmem_allocation
*next
=
114 list_entry(allocation
->entry
.next
,
115 struct intmem_allocation
, entry
);
117 allocation
->status
= STATUS_FREE
;
118 /* Join with prev and/or next if also free */
119 if ((prev
!= &intmem_allocations
) &&
120 (prev
->status
== STATUS_FREE
)) {
121 prev
->size
+= allocation
->size
;
122 list_del(&allocation
->entry
);
126 if ((next
!= &intmem_allocations
) &&
127 (next
->status
== STATUS_FREE
)) {
128 allocation
->size
+= next
->size
;
129 list_del(&next
->entry
);
139 void* crisv32_intmem_phys_to_virt(unsigned long addr
)
141 return (void *)(addr
- (MEM_INTMEM_START
+ RESERVED_SIZE
) +
142 (unsigned long)intmem_virtual
);
145 unsigned long crisv32_intmem_virt_to_phys(void* addr
)
147 return (unsigned long)((unsigned long )addr
-
148 (unsigned long)intmem_virtual
+ MEM_INTMEM_START
+
152 module_init(crisv32_intmem_init
);