Commit | Line | Data |
---|---|---|
1394f032 | 1 | /* |
96f1050d | 2 | * SRAM allocator for Blackfin on-chip memory |
1394f032 | 3 | * |
96f1050d | 4 | * Copyright 2004-2009 Analog Devices Inc. |
1394f032 | 5 | * |
96f1050d | 6 | * Licensed under the GPL-2 or later. |
1394f032 BW |
7 | */ |
8 | ||
1394f032 BW |
9 | #include <linux/module.h> |
10 | #include <linux/kernel.h> | |
11 | #include <linux/types.h> | |
12 | #include <linux/miscdevice.h> | |
13 | #include <linux/ioport.h> | |
14 | #include <linux/fcntl.h> | |
15 | #include <linux/init.h> | |
16 | #include <linux/poll.h> | |
17 | #include <linux/proc_fs.h> | |
18 | #include <linux/spinlock.h> | |
19 | #include <linux/rtc.h> | |
5a0e3ad6 | 20 | #include <linux/slab.h> |
1394f032 | 21 | #include <asm/blackfin.h> |
dbc895f9 | 22 | #include <asm/mem_map.h> |
1394f032 BW |
23 | #include "blackfin_sram.h" |
24 | ||
1394f032 | 25 | /* the data structure for L1 scratchpad and DATA SRAM */ |
5d481f49 | 26 | struct sram_piece { |
1394f032 BW |
27 | void *paddr; |
28 | int size; | |
bc61b4e6 | 29 | pid_t pid; |
5d481f49 | 30 | struct sram_piece *next; |
1394f032 BW |
31 | }; |
32 | ||
81c969a8 | 33 | static DEFINE_PER_CPU_SHARED_ALIGNED(spinlock_t, l1sram_lock); |
8f65873e GY |
34 | static DEFINE_PER_CPU(struct sram_piece, free_l1_ssram_head); |
35 | static DEFINE_PER_CPU(struct sram_piece, used_l1_ssram_head); | |
1394f032 BW |
36 | |
37 | #if L1_DATA_A_LENGTH != 0 | |
8f65873e GY |
38 | static DEFINE_PER_CPU(struct sram_piece, free_l1_data_A_sram_head); |
39 | static DEFINE_PER_CPU(struct sram_piece, used_l1_data_A_sram_head); | |
1394f032 BW |
40 | #endif |
41 | ||
42 | #if L1_DATA_B_LENGTH != 0 | |
8f65873e GY |
43 | static DEFINE_PER_CPU(struct sram_piece, free_l1_data_B_sram_head); |
44 | static DEFINE_PER_CPU(struct sram_piece, used_l1_data_B_sram_head); | |
1394f032 BW |
45 | #endif |
46 | ||
81c969a8 MF |
47 | #if L1_DATA_A_LENGTH || L1_DATA_B_LENGTH |
48 | static DEFINE_PER_CPU_SHARED_ALIGNED(spinlock_t, l1_data_sram_lock); | |
49 | #endif | |
50 | ||
1394f032 | 51 | #if L1_CODE_LENGTH != 0 |
81c969a8 | 52 | static DEFINE_PER_CPU_SHARED_ALIGNED(spinlock_t, l1_inst_sram_lock); |
8f65873e GY |
53 | static DEFINE_PER_CPU(struct sram_piece, free_l1_inst_sram_head); |
54 | static DEFINE_PER_CPU(struct sram_piece, used_l1_inst_sram_head); | |
1394f032 BW |
55 | #endif |
56 | ||
07aa7be5 | 57 | #if L2_LENGTH != 0 |
81c969a8 | 58 | static spinlock_t l2_sram_lock ____cacheline_aligned_in_smp; |
262c3825 SZ |
59 | static struct sram_piece free_l2_sram_head, used_l2_sram_head; |
60 | #endif | |
61 | ||
5d481f49 SZ |
62 | static struct kmem_cache *sram_piece_cache; |
63 | ||
1394f032 | 64 | /* L1 Scratchpad SRAM initialization function */ |
5d481f49 | 65 | static void __init l1sram_init(void) |
1394f032 | 66 | { |
8f65873e | 67 | unsigned int cpu; |
89ecd506 GY |
68 | unsigned long reserve; |
69 | ||
70 | #ifdef CONFIG_SMP | |
71 | reserve = 0; | |
72 | #else | |
73 | reserve = sizeof(struct l1_scratch_task_info); | |
74 | #endif | |
75 | ||
8f65873e GY |
76 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
77 | per_cpu(free_l1_ssram_head, cpu).next = | |
78 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
79 | if (!per_cpu(free_l1_ssram_head, cpu).next) { | |
80 | printk(KERN_INFO "Fail to initialize Scratchpad data SRAM.\n"); | |
81 | return; | |
82 | } | |
83 | ||
89ecd506 GY |
84 | per_cpu(free_l1_ssram_head, cpu).next->paddr = (void *)get_l1_scratch_start_cpu(cpu) + reserve; |
85 | per_cpu(free_l1_ssram_head, cpu).next->size = L1_SCRATCH_LENGTH - reserve; | |
8f65873e GY |
86 | per_cpu(free_l1_ssram_head, cpu).next->pid = 0; |
87 | per_cpu(free_l1_ssram_head, cpu).next->next = NULL; | |
88 | ||
89 | per_cpu(used_l1_ssram_head, cpu).next = NULL; | |
90 | ||
91 | /* mutex initialize */ | |
92 | spin_lock_init(&per_cpu(l1sram_lock, cpu)); | |
93 | printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n", | |
94 | L1_SCRATCH_LENGTH >> 10); | |
5d481f49 | 95 | } |
1394f032 BW |
96 | } |
97 | ||
5d481f49 | 98 | static void __init l1_data_sram_init(void) |
1394f032 | 99 | { |
0b82e274 | 100 | #if L1_DATA_A_LENGTH != 0 || L1_DATA_B_LENGTH != 0 |
8f65873e | 101 | unsigned int cpu; |
0b82e274 | 102 | #endif |
1394f032 | 103 | #if L1_DATA_A_LENGTH != 0 |
8f65873e GY |
104 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
105 | per_cpu(free_l1_data_A_sram_head, cpu).next = | |
106 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
107 | if (!per_cpu(free_l1_data_A_sram_head, cpu).next) { | |
108 | printk(KERN_INFO "Fail to initialize L1 Data A SRAM.\n"); | |
109 | return; | |
110 | } | |
111 | ||
112 | per_cpu(free_l1_data_A_sram_head, cpu).next->paddr = | |
113 | (void *)get_l1_data_a_start_cpu(cpu) + (_ebss_l1 - _sdata_l1); | |
114 | per_cpu(free_l1_data_A_sram_head, cpu).next->size = | |
115 | L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1); | |
116 | per_cpu(free_l1_data_A_sram_head, cpu).next->pid = 0; | |
117 | per_cpu(free_l1_data_A_sram_head, cpu).next->next = NULL; | |
118 | ||
119 | per_cpu(used_l1_data_A_sram_head, cpu).next = NULL; | |
120 | ||
121 | printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n", | |
122 | L1_DATA_A_LENGTH >> 10, | |
123 | per_cpu(free_l1_data_A_sram_head, cpu).next->size >> 10); | |
5d481f49 | 124 | } |
1394f032 BW |
125 | #endif |
126 | #if L1_DATA_B_LENGTH != 0 | |
8f65873e GY |
127 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
128 | per_cpu(free_l1_data_B_sram_head, cpu).next = | |
129 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
130 | if (!per_cpu(free_l1_data_B_sram_head, cpu).next) { | |
131 | printk(KERN_INFO "Fail to initialize L1 Data B SRAM.\n"); | |
132 | return; | |
133 | } | |
134 | ||
135 | per_cpu(free_l1_data_B_sram_head, cpu).next->paddr = | |
136 | (void *)get_l1_data_b_start_cpu(cpu) + (_ebss_b_l1 - _sdata_b_l1); | |
137 | per_cpu(free_l1_data_B_sram_head, cpu).next->size = | |
138 | L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1); | |
139 | per_cpu(free_l1_data_B_sram_head, cpu).next->pid = 0; | |
140 | per_cpu(free_l1_data_B_sram_head, cpu).next->next = NULL; | |
141 | ||
142 | per_cpu(used_l1_data_B_sram_head, cpu).next = NULL; | |
143 | ||
144 | printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n", | |
145 | L1_DATA_B_LENGTH >> 10, | |
146 | per_cpu(free_l1_data_B_sram_head, cpu).next->size >> 10); | |
147 | /* mutex initialize */ | |
5d481f49 | 148 | } |
1394f032 BW |
149 | #endif |
150 | ||
8f65873e GY |
151 | #if L1_DATA_A_LENGTH != 0 || L1_DATA_B_LENGTH != 0 |
152 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) | |
153 | spin_lock_init(&per_cpu(l1_data_sram_lock, cpu)); | |
154 | #endif | |
1394f032 BW |
155 | } |
156 | ||
5d481f49 | 157 | static void __init l1_inst_sram_init(void) |
1394f032 BW |
158 | { |
159 | #if L1_CODE_LENGTH != 0 | |
8f65873e GY |
160 | unsigned int cpu; |
161 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { | |
162 | per_cpu(free_l1_inst_sram_head, cpu).next = | |
163 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
164 | if (!per_cpu(free_l1_inst_sram_head, cpu).next) { | |
165 | printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n"); | |
166 | return; | |
167 | } | |
168 | ||
169 | per_cpu(free_l1_inst_sram_head, cpu).next->paddr = | |
170 | (void *)get_l1_code_start_cpu(cpu) + (_etext_l1 - _stext_l1); | |
171 | per_cpu(free_l1_inst_sram_head, cpu).next->size = | |
172 | L1_CODE_LENGTH - (_etext_l1 - _stext_l1); | |
173 | per_cpu(free_l1_inst_sram_head, cpu).next->pid = 0; | |
174 | per_cpu(free_l1_inst_sram_head, cpu).next->next = NULL; | |
175 | ||
176 | per_cpu(used_l1_inst_sram_head, cpu).next = NULL; | |
177 | ||
178 | printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n", | |
179 | L1_CODE_LENGTH >> 10, | |
180 | per_cpu(free_l1_inst_sram_head, cpu).next->size >> 10); | |
181 | ||
182 | /* mutex initialize */ | |
183 | spin_lock_init(&per_cpu(l1_inst_sram_lock, cpu)); | |
5d481f49 | 184 | } |
1394f032 | 185 | #endif |
1394f032 BW |
186 | } |
187 | ||
262c3825 SZ |
188 | static void __init l2_sram_init(void) |
189 | { | |
07aa7be5 | 190 | #if L2_LENGTH != 0 |
262c3825 SZ |
191 | free_l2_sram_head.next = |
192 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
193 | if (!free_l2_sram_head.next) { | |
8f65873e | 194 | printk(KERN_INFO "Fail to initialize L2 SRAM.\n"); |
262c3825 SZ |
195 | return; |
196 | } | |
197 | ||
b2c2f303 JZ |
198 | free_l2_sram_head.next->paddr = |
199 | (void *)L2_START + (_ebss_l2 - _stext_l2); | |
200 | free_l2_sram_head.next->size = | |
201 | L2_LENGTH - (_ebss_l2 - _stext_l2); | |
262c3825 SZ |
202 | free_l2_sram_head.next->pid = 0; |
203 | free_l2_sram_head.next->next = NULL; | |
204 | ||
205 | used_l2_sram_head.next = NULL; | |
206 | ||
207 | printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n", | |
208 | L2_LENGTH >> 10, | |
209 | free_l2_sram_head.next->size >> 10); | |
262c3825 SZ |
210 | |
211 | /* mutex initialize */ | |
212 | spin_lock_init(&l2_sram_lock); | |
81c969a8 | 213 | #endif |
262c3825 | 214 | } |
8f65873e | 215 | |
c72aa079 | 216 | static int __init bfin_sram_init(void) |
5d481f49 SZ |
217 | { |
218 | sram_piece_cache = kmem_cache_create("sram_piece_cache", | |
219 | sizeof(struct sram_piece), | |
220 | 0, SLAB_PANIC, NULL); | |
221 | ||
222 | l1sram_init(); | |
223 | l1_data_sram_init(); | |
224 | l1_inst_sram_init(); | |
262c3825 | 225 | l2_sram_init(); |
c72aa079 GY |
226 | |
227 | return 0; | |
5d481f49 | 228 | } |
c72aa079 | 229 | pure_initcall(bfin_sram_init); |
5d481f49 | 230 | |
262c3825 SZ |
231 | /* SRAM allocate function */ |
232 | static void *_sram_alloc(size_t size, struct sram_piece *pfree_head, | |
5d481f49 | 233 | struct sram_piece *pused_head) |
1394f032 | 234 | { |
5d481f49 | 235 | struct sram_piece *pslot, *plast, *pavail; |
1394f032 | 236 | |
5d481f49 | 237 | if (size <= 0 || !pfree_head || !pused_head) |
1394f032 BW |
238 | return NULL; |
239 | ||
240 | /* Align the size */ | |
241 | size = (size + 3) & ~3; | |
242 | ||
5d481f49 SZ |
243 | pslot = pfree_head->next; |
244 | plast = pfree_head; | |
245 | ||
246 | /* search an available piece slot */ | |
247 | while (pslot != NULL && size > pslot->size) { | |
248 | plast = pslot; | |
249 | pslot = pslot->next; | |
1394f032 | 250 | } |
5d481f49 SZ |
251 | |
252 | if (!pslot) | |
1394f032 BW |
253 | return NULL; |
254 | ||
5d481f49 SZ |
255 | if (pslot->size == size) { |
256 | plast->next = pslot->next; | |
257 | pavail = pslot; | |
258 | } else { | |
259 | pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
260 | ||
261 | if (!pavail) | |
262 | return NULL; | |
263 | ||
264 | pavail->paddr = pslot->paddr; | |
265 | pavail->size = size; | |
266 | pslot->paddr += size; | |
267 | pslot->size -= size; | |
1394f032 BW |
268 | } |
269 | ||
5d481f49 SZ |
270 | pavail->pid = current->pid; |
271 | ||
272 | pslot = pused_head->next; | |
273 | plast = pused_head; | |
274 | ||
275 | /* insert new piece into used piece list !!! */ | |
276 | while (pslot != NULL && pavail->paddr < pslot->paddr) { | |
277 | plast = pslot; | |
278 | pslot = pslot->next; | |
279 | } | |
280 | ||
281 | pavail->next = pslot; | |
282 | plast->next = pavail; | |
283 | ||
284 | return pavail->paddr; | |
1394f032 BW |
285 | } |
286 | ||
287 | /* Allocate the largest available block. */ | |
262c3825 | 288 | static void *_sram_alloc_max(struct sram_piece *pfree_head, |
5d481f49 | 289 | struct sram_piece *pused_head, |
1394f032 BW |
290 | unsigned long *psize) |
291 | { | |
5d481f49 SZ |
292 | struct sram_piece *pslot, *pmax; |
293 | ||
294 | if (!pfree_head || !pused_head) | |
295 | return NULL; | |
296 | ||
297 | pmax = pslot = pfree_head->next; | |
1394f032 | 298 | |
5d481f49 SZ |
299 | /* search an available piece slot */ |
300 | while (pslot != NULL) { | |
301 | if (pslot->size > pmax->size) | |
302 | pmax = pslot; | |
303 | pslot = pslot->next; | |
1394f032 | 304 | } |
5d481f49 SZ |
305 | |
306 | if (!pmax) | |
1394f032 | 307 | return NULL; |
1394f032 | 308 | |
5d481f49 SZ |
309 | *psize = pmax->size; |
310 | ||
262c3825 | 311 | return _sram_alloc(*psize, pfree_head, pused_head); |
1394f032 BW |
312 | } |
313 | ||
262c3825 SZ |
314 | /* SRAM free function */ |
315 | static int _sram_free(const void *addr, | |
5d481f49 SZ |
316 | struct sram_piece *pfree_head, |
317 | struct sram_piece *pused_head) | |
1394f032 | 318 | { |
5d481f49 SZ |
319 | struct sram_piece *pslot, *plast, *pavail; |
320 | ||
321 | if (!pfree_head || !pused_head) | |
322 | return -1; | |
1394f032 BW |
323 | |
324 | /* search the relevant memory slot */ | |
5d481f49 SZ |
325 | pslot = pused_head->next; |
326 | plast = pused_head; | |
327 | ||
328 | /* search an available piece slot */ | |
329 | while (pslot != NULL && pslot->paddr != addr) { | |
330 | plast = pslot; | |
331 | pslot = pslot->next; | |
1394f032 | 332 | } |
5d481f49 SZ |
333 | |
334 | if (!pslot) | |
1394f032 BW |
335 | return -1; |
336 | ||
5d481f49 SZ |
337 | plast->next = pslot->next; |
338 | pavail = pslot; | |
339 | pavail->pid = 0; | |
340 | ||
341 | /* insert free pieces back to the free list */ | |
342 | pslot = pfree_head->next; | |
343 | plast = pfree_head; | |
344 | ||
345 | while (pslot != NULL && addr > pslot->paddr) { | |
346 | plast = pslot; | |
347 | pslot = pslot->next; | |
348 | } | |
349 | ||
350 | if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) { | |
351 | plast->size += pavail->size; | |
352 | kmem_cache_free(sram_piece_cache, pavail); | |
353 | } else { | |
225f7e1e | 354 | pavail->next = plast->next; |
5d481f49 SZ |
355 | plast->next = pavail; |
356 | plast = pavail; | |
1394f032 BW |
357 | } |
358 | ||
5d481f49 SZ |
359 | if (pslot && plast->paddr + plast->size == pslot->paddr) { |
360 | plast->size += pslot->size; | |
361 | plast->next = pslot->next; | |
362 | kmem_cache_free(sram_piece_cache, pslot); | |
1394f032 BW |
363 | } |
364 | ||
365 | return 0; | |
366 | } | |
367 | ||
368 | int sram_free(const void *addr) | |
369 | { | |
5e95320f | 370 | |
1394f032 | 371 | #if L1_CODE_LENGTH != 0 |
8f65873e GY |
372 | if (addr >= (void *)get_l1_code_start() |
373 | && addr < (void *)(get_l1_code_start() + L1_CODE_LENGTH)) | |
1394f032 | 374 | return l1_inst_sram_free(addr); |
5e95320f | 375 | else |
1394f032 BW |
376 | #endif |
377 | #if L1_DATA_A_LENGTH != 0 | |
8f65873e GY |
378 | if (addr >= (void *)get_l1_data_a_start() |
379 | && addr < (void *)(get_l1_data_a_start() + L1_DATA_A_LENGTH)) | |
1394f032 | 380 | return l1_data_A_sram_free(addr); |
5e95320f | 381 | else |
1394f032 BW |
382 | #endif |
383 | #if L1_DATA_B_LENGTH != 0 | |
8f65873e GY |
384 | if (addr >= (void *)get_l1_data_b_start() |
385 | && addr < (void *)(get_l1_data_b_start() + L1_DATA_B_LENGTH)) | |
1394f032 | 386 | return l1_data_B_sram_free(addr); |
5e95320f | 387 | else |
262c3825 | 388 | #endif |
07aa7be5 | 389 | #if L2_LENGTH != 0 |
5e95320f | 390 | if (addr >= (void *)L2_START |
262c3825 SZ |
391 | && addr < (void *)(L2_START + L2_LENGTH)) |
392 | return l2_sram_free(addr); | |
1394f032 | 393 | else |
5e95320f | 394 | #endif |
1394f032 BW |
395 | return -1; |
396 | } | |
397 | EXPORT_SYMBOL(sram_free); | |
398 | ||
399 | void *l1_data_A_sram_alloc(size_t size) | |
400 | { | |
81c969a8 | 401 | #if L1_DATA_A_LENGTH != 0 |
226a6ec3 | 402 | unsigned long flags; |
81c969a8 | 403 | void *addr; |
8f65873e | 404 | unsigned int cpu; |
1394f032 | 405 | |
54536c5c | 406 | cpu = smp_processor_id(); |
1394f032 | 407 | /* add mutex operation */ |
8f65873e | 408 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 | 409 | |
8f65873e GY |
410 | addr = _sram_alloc(size, &per_cpu(free_l1_data_A_sram_head, cpu), |
411 | &per_cpu(used_l1_data_A_sram_head, cpu)); | |
1394f032 BW |
412 | |
413 | /* add mutex operation */ | |
8f65873e | 414 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 BW |
415 | |
416 | pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n", | |
417 | (long unsigned int)addr, size); | |
418 | ||
419 | return addr; | |
81c969a8 MF |
420 | #else |
421 | return NULL; | |
422 | #endif | |
1394f032 BW |
423 | } |
424 | EXPORT_SYMBOL(l1_data_A_sram_alloc); | |
425 | ||
426 | int l1_data_A_sram_free(const void *addr) | |
427 | { | |
81c969a8 | 428 | #if L1_DATA_A_LENGTH != 0 |
226a6ec3 | 429 | unsigned long flags; |
1394f032 | 430 | int ret; |
8f65873e | 431 | unsigned int cpu; |
1394f032 | 432 | |
54536c5c | 433 | cpu = smp_processor_id(); |
1394f032 | 434 | /* add mutex operation */ |
8f65873e | 435 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 | 436 | |
8f65873e GY |
437 | ret = _sram_free(addr, &per_cpu(free_l1_data_A_sram_head, cpu), |
438 | &per_cpu(used_l1_data_A_sram_head, cpu)); | |
1394f032 BW |
439 | |
440 | /* add mutex operation */ | |
8f65873e | 441 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 BW |
442 | |
443 | return ret; | |
81c969a8 MF |
444 | #else |
445 | return -1; | |
446 | #endif | |
1394f032 BW |
447 | } |
448 | EXPORT_SYMBOL(l1_data_A_sram_free); | |
449 | ||
450 | void *l1_data_B_sram_alloc(size_t size) | |
451 | { | |
452 | #if L1_DATA_B_LENGTH != 0 | |
226a6ec3 | 453 | unsigned long flags; |
1394f032 | 454 | void *addr; |
8f65873e | 455 | unsigned int cpu; |
1394f032 | 456 | |
54536c5c | 457 | cpu = smp_processor_id(); |
1394f032 | 458 | /* add mutex operation */ |
8f65873e | 459 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 | 460 | |
8f65873e GY |
461 | addr = _sram_alloc(size, &per_cpu(free_l1_data_B_sram_head, cpu), |
462 | &per_cpu(used_l1_data_B_sram_head, cpu)); | |
1394f032 BW |
463 | |
464 | /* add mutex operation */ | |
8f65873e | 465 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 BW |
466 | |
467 | pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n", | |
468 | (long unsigned int)addr, size); | |
469 | ||
470 | return addr; | |
471 | #else | |
472 | return NULL; | |
473 | #endif | |
474 | } | |
475 | EXPORT_SYMBOL(l1_data_B_sram_alloc); | |
476 | ||
477 | int l1_data_B_sram_free(const void *addr) | |
478 | { | |
479 | #if L1_DATA_B_LENGTH != 0 | |
226a6ec3 | 480 | unsigned long flags; |
1394f032 | 481 | int ret; |
8f65873e | 482 | unsigned int cpu; |
1394f032 | 483 | |
54536c5c | 484 | cpu = smp_processor_id(); |
1394f032 | 485 | /* add mutex operation */ |
8f65873e | 486 | spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 | 487 | |
8f65873e GY |
488 | ret = _sram_free(addr, &per_cpu(free_l1_data_B_sram_head, cpu), |
489 | &per_cpu(used_l1_data_B_sram_head, cpu)); | |
1394f032 BW |
490 | |
491 | /* add mutex operation */ | |
8f65873e | 492 | spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags); |
1394f032 BW |
493 | |
494 | return ret; | |
495 | #else | |
496 | return -1; | |
497 | #endif | |
498 | } | |
499 | EXPORT_SYMBOL(l1_data_B_sram_free); | |
500 | ||
501 | void *l1_data_sram_alloc(size_t size) | |
502 | { | |
503 | void *addr = l1_data_A_sram_alloc(size); | |
504 | ||
505 | if (!addr) | |
506 | addr = l1_data_B_sram_alloc(size); | |
507 | ||
508 | return addr; | |
509 | } | |
510 | EXPORT_SYMBOL(l1_data_sram_alloc); | |
511 | ||
512 | void *l1_data_sram_zalloc(size_t size) | |
513 | { | |
514 | void *addr = l1_data_sram_alloc(size); | |
515 | ||
516 | if (addr) | |
517 | memset(addr, 0x00, size); | |
518 | ||
519 | return addr; | |
520 | } | |
521 | EXPORT_SYMBOL(l1_data_sram_zalloc); | |
522 | ||
523 | int l1_data_sram_free(const void *addr) | |
524 | { | |
525 | int ret; | |
526 | ret = l1_data_A_sram_free(addr); | |
527 | if (ret == -1) | |
528 | ret = l1_data_B_sram_free(addr); | |
529 | return ret; | |
530 | } | |
531 | EXPORT_SYMBOL(l1_data_sram_free); | |
532 | ||
533 | void *l1_inst_sram_alloc(size_t size) | |
534 | { | |
c5b50df8 | 535 | #if L1_CODE_LENGTH != 0 |
226a6ec3 | 536 | unsigned long flags; |
1394f032 | 537 | void *addr; |
8f65873e | 538 | unsigned int cpu; |
1394f032 | 539 | |
54536c5c | 540 | cpu = smp_processor_id(); |
1394f032 | 541 | /* add mutex operation */ |
8f65873e | 542 | spin_lock_irqsave(&per_cpu(l1_inst_sram_lock, cpu), flags); |
1394f032 | 543 | |
8f65873e GY |
544 | addr = _sram_alloc(size, &per_cpu(free_l1_inst_sram_head, cpu), |
545 | &per_cpu(used_l1_inst_sram_head, cpu)); | |
1394f032 BW |
546 | |
547 | /* add mutex operation */ | |
8f65873e | 548 | spin_unlock_irqrestore(&per_cpu(l1_inst_sram_lock, cpu), flags); |
1394f032 BW |
549 | |
550 | pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n", | |
551 | (long unsigned int)addr, size); | |
552 | ||
553 | return addr; | |
554 | #else | |
555 | return NULL; | |
556 | #endif | |
557 | } | |
558 | EXPORT_SYMBOL(l1_inst_sram_alloc); | |
559 | ||
560 | int l1_inst_sram_free(const void *addr) | |
561 | { | |
562 | #if L1_CODE_LENGTH != 0 | |
226a6ec3 | 563 | unsigned long flags; |
1394f032 | 564 | int ret; |
8f65873e | 565 | unsigned int cpu; |
1394f032 | 566 | |
54536c5c | 567 | cpu = smp_processor_id(); |
1394f032 | 568 | /* add mutex operation */ |
8f65873e | 569 | spin_lock_irqsave(&per_cpu(l1_inst_sram_lock, cpu), flags); |
1394f032 | 570 | |
8f65873e GY |
571 | ret = _sram_free(addr, &per_cpu(free_l1_inst_sram_head, cpu), |
572 | &per_cpu(used_l1_inst_sram_head, cpu)); | |
1394f032 BW |
573 | |
574 | /* add mutex operation */ | |
8f65873e | 575 | spin_unlock_irqrestore(&per_cpu(l1_inst_sram_lock, cpu), flags); |
1394f032 BW |
576 | |
577 | return ret; | |
578 | #else | |
579 | return -1; | |
580 | #endif | |
581 | } | |
582 | EXPORT_SYMBOL(l1_inst_sram_free); | |
583 | ||
584 | /* L1 Scratchpad memory allocate function */ | |
585 | void *l1sram_alloc(size_t size) | |
586 | { | |
226a6ec3 | 587 | unsigned long flags; |
1394f032 | 588 | void *addr; |
8f65873e | 589 | unsigned int cpu; |
1394f032 | 590 | |
54536c5c | 591 | cpu = smp_processor_id(); |
1394f032 | 592 | /* add mutex operation */ |
8f65873e | 593 | spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags); |
1394f032 | 594 | |
8f65873e GY |
595 | addr = _sram_alloc(size, &per_cpu(free_l1_ssram_head, cpu), |
596 | &per_cpu(used_l1_ssram_head, cpu)); | |
1394f032 BW |
597 | |
598 | /* add mutex operation */ | |
8f65873e | 599 | spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags); |
1394f032 BW |
600 | |
601 | return addr; | |
602 | } | |
603 | ||
604 | /* L1 Scratchpad memory allocate function */ | |
605 | void *l1sram_alloc_max(size_t *psize) | |
606 | { | |
226a6ec3 | 607 | unsigned long flags; |
1394f032 | 608 | void *addr; |
8f65873e | 609 | unsigned int cpu; |
1394f032 | 610 | |
54536c5c | 611 | cpu = smp_processor_id(); |
1394f032 | 612 | /* add mutex operation */ |
8f65873e | 613 | spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags); |
1394f032 | 614 | |
8f65873e GY |
615 | addr = _sram_alloc_max(&per_cpu(free_l1_ssram_head, cpu), |
616 | &per_cpu(used_l1_ssram_head, cpu), psize); | |
1394f032 BW |
617 | |
618 | /* add mutex operation */ | |
8f65873e | 619 | spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags); |
1394f032 BW |
620 | |
621 | return addr; | |
622 | } | |
623 | ||
624 | /* L1 Scratchpad memory free function */ | |
625 | int l1sram_free(const void *addr) | |
626 | { | |
226a6ec3 | 627 | unsigned long flags; |
1394f032 | 628 | int ret; |
8f65873e | 629 | unsigned int cpu; |
1394f032 | 630 | |
54536c5c | 631 | cpu = smp_processor_id(); |
1394f032 | 632 | /* add mutex operation */ |
8f65873e | 633 | spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags); |
1394f032 | 634 | |
8f65873e GY |
635 | ret = _sram_free(addr, &per_cpu(free_l1_ssram_head, cpu), |
636 | &per_cpu(used_l1_ssram_head, cpu)); | |
1394f032 BW |
637 | |
638 | /* add mutex operation */ | |
8f65873e | 639 | spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags); |
1394f032 BW |
640 | |
641 | return ret; | |
642 | } | |
643 | ||
262c3825 SZ |
644 | void *l2_sram_alloc(size_t size) |
645 | { | |
07aa7be5 | 646 | #if L2_LENGTH != 0 |
226a6ec3 | 647 | unsigned long flags; |
262c3825 SZ |
648 | void *addr; |
649 | ||
650 | /* add mutex operation */ | |
651 | spin_lock_irqsave(&l2_sram_lock, flags); | |
652 | ||
653 | addr = _sram_alloc(size, &free_l2_sram_head, | |
654 | &used_l2_sram_head); | |
655 | ||
656 | /* add mutex operation */ | |
657 | spin_unlock_irqrestore(&l2_sram_lock, flags); | |
658 | ||
659 | pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n", | |
660 | (long unsigned int)addr, size); | |
661 | ||
662 | return addr; | |
663 | #else | |
664 | return NULL; | |
665 | #endif | |
666 | } | |
667 | EXPORT_SYMBOL(l2_sram_alloc); | |
668 | ||
669 | void *l2_sram_zalloc(size_t size) | |
670 | { | |
671 | void *addr = l2_sram_alloc(size); | |
672 | ||
673 | if (addr) | |
674 | memset(addr, 0x00, size); | |
675 | ||
676 | return addr; | |
677 | } | |
678 | EXPORT_SYMBOL(l2_sram_zalloc); | |
679 | ||
680 | int l2_sram_free(const void *addr) | |
681 | { | |
07aa7be5 | 682 | #if L2_LENGTH != 0 |
226a6ec3 | 683 | unsigned long flags; |
262c3825 SZ |
684 | int ret; |
685 | ||
686 | /* add mutex operation */ | |
687 | spin_lock_irqsave(&l2_sram_lock, flags); | |
688 | ||
689 | ret = _sram_free(addr, &free_l2_sram_head, | |
690 | &used_l2_sram_head); | |
691 | ||
692 | /* add mutex operation */ | |
693 | spin_unlock_irqrestore(&l2_sram_lock, flags); | |
694 | ||
695 | return ret; | |
696 | #else | |
697 | return -1; | |
698 | #endif | |
699 | } | |
700 | EXPORT_SYMBOL(l2_sram_free); | |
701 | ||
1394f032 BW |
702 | int sram_free_with_lsl(const void *addr) |
703 | { | |
704 | struct sram_list_struct *lsl, **tmp; | |
705 | struct mm_struct *mm = current->mm; | |
706 | ||
707 | for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next) | |
708 | if ((*tmp)->addr == addr) | |
709 | goto found; | |
710 | return -1; | |
711 | found: | |
712 | lsl = *tmp; | |
713 | sram_free(addr); | |
714 | *tmp = lsl->next; | |
715 | kfree(lsl); | |
716 | ||
717 | return 0; | |
718 | } | |
719 | EXPORT_SYMBOL(sram_free_with_lsl); | |
720 | ||
f1db88d2 MF |
721 | /* Allocate memory and keep in L1 SRAM List (lsl) so that the resources are |
722 | * tracked. These are designed for userspace so that when a process exits, | |
723 | * we can safely reap their resources. | |
724 | */ | |
1394f032 BW |
725 | void *sram_alloc_with_lsl(size_t size, unsigned long flags) |
726 | { | |
727 | void *addr = NULL; | |
728 | struct sram_list_struct *lsl = NULL; | |
729 | struct mm_struct *mm = current->mm; | |
730 | ||
dd00cc48 | 731 | lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL); |
1394f032 BW |
732 | if (!lsl) |
733 | return NULL; | |
1394f032 BW |
734 | |
735 | if (flags & L1_INST_SRAM) | |
736 | addr = l1_inst_sram_alloc(size); | |
737 | ||
738 | if (addr == NULL && (flags & L1_DATA_A_SRAM)) | |
739 | addr = l1_data_A_sram_alloc(size); | |
740 | ||
741 | if (addr == NULL && (flags & L1_DATA_B_SRAM)) | |
742 | addr = l1_data_B_sram_alloc(size); | |
743 | ||
262c3825 SZ |
744 | if (addr == NULL && (flags & L2_SRAM)) |
745 | addr = l2_sram_alloc(size); | |
746 | ||
1394f032 BW |
747 | if (addr == NULL) { |
748 | kfree(lsl); | |
749 | return NULL; | |
750 | } | |
751 | lsl->addr = addr; | |
752 | lsl->length = size; | |
753 | lsl->next = mm->context.sram_list; | |
754 | mm->context.sram_list = lsl; | |
755 | return addr; | |
756 | } | |
757 | EXPORT_SYMBOL(sram_alloc_with_lsl); | |
bc61b4e6 MF |
758 | |
759 | #ifdef CONFIG_PROC_FS | |
760 | /* Once we get a real allocator, we'll throw all of this away. | |
761 | * Until then, we need some sort of visibility into the L1 alloc. | |
762 | */ | |
260d5d35 MF |
763 | /* Need to keep line of output the same. Currently, that is 44 bytes |
764 | * (including newline). | |
765 | */ | |
262c3825 | 766 | static int _sram_proc_read(char *buf, int *len, int count, const char *desc, |
5d481f49 SZ |
767 | struct sram_piece *pfree_head, |
768 | struct sram_piece *pused_head) | |
bc61b4e6 | 769 | { |
5d481f49 SZ |
770 | struct sram_piece *pslot; |
771 | ||
772 | if (!pfree_head || !pused_head) | |
773 | return -1; | |
bc61b4e6 | 774 | |
262c3825 | 775 | *len += sprintf(&buf[*len], "--- SRAM %-14s Size PID State \n", desc); |
5d481f49 SZ |
776 | |
777 | /* search the relevant memory slot */ | |
778 | pslot = pused_head->next; | |
779 | ||
780 | while (pslot != NULL) { | |
262c3825 | 781 | *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", |
5d481f49 SZ |
782 | pslot->paddr, pslot->paddr + pslot->size, |
783 | pslot->size, pslot->pid, "ALLOCATED"); | |
784 | ||
785 | pslot = pslot->next; | |
786 | } | |
787 | ||
788 | pslot = pfree_head->next; | |
789 | ||
790 | while (pslot != NULL) { | |
262c3825 | 791 | *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", |
5d481f49 SZ |
792 | pslot->paddr, pslot->paddr + pslot->size, |
793 | pslot->size, pslot->pid, "FREE"); | |
794 | ||
795 | pslot = pslot->next; | |
bc61b4e6 | 796 | } |
5d481f49 SZ |
797 | |
798 | return 0; | |
bc61b4e6 | 799 | } |
262c3825 | 800 | static int sram_proc_read(char *buf, char **start, off_t offset, int count, |
bc61b4e6 MF |
801 | int *eof, void *data) |
802 | { | |
803 | int len = 0; | |
8f65873e | 804 | unsigned int cpu; |
bc61b4e6 | 805 | |
8f65873e GY |
806 | for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { |
807 | if (_sram_proc_read(buf, &len, count, "Scratchpad", | |
808 | &per_cpu(free_l1_ssram_head, cpu), &per_cpu(used_l1_ssram_head, cpu))) | |
809 | goto not_done; | |
bc61b4e6 | 810 | #if L1_DATA_A_LENGTH != 0 |
8f65873e GY |
811 | if (_sram_proc_read(buf, &len, count, "L1 Data A", |
812 | &per_cpu(free_l1_data_A_sram_head, cpu), | |
813 | &per_cpu(used_l1_data_A_sram_head, cpu))) | |
814 | goto not_done; | |
bc61b4e6 MF |
815 | #endif |
816 | #if L1_DATA_B_LENGTH != 0 | |
8f65873e GY |
817 | if (_sram_proc_read(buf, &len, count, "L1 Data B", |
818 | &per_cpu(free_l1_data_B_sram_head, cpu), | |
819 | &per_cpu(used_l1_data_B_sram_head, cpu))) | |
820 | goto not_done; | |
bc61b4e6 MF |
821 | #endif |
822 | #if L1_CODE_LENGTH != 0 | |
8f65873e GY |
823 | if (_sram_proc_read(buf, &len, count, "L1 Instruction", |
824 | &per_cpu(free_l1_inst_sram_head, cpu), | |
825 | &per_cpu(used_l1_inst_sram_head, cpu))) | |
826 | goto not_done; | |
bc61b4e6 | 827 | #endif |
8f65873e | 828 | } |
07aa7be5 | 829 | #if L2_LENGTH != 0 |
8f65873e GY |
830 | if (_sram_proc_read(buf, &len, count, "L2", &free_l2_sram_head, |
831 | &used_l2_sram_head)) | |
262c3825 SZ |
832 | goto not_done; |
833 | #endif | |
260d5d35 MF |
834 | *eof = 1; |
835 | not_done: | |
bc61b4e6 MF |
836 | return len; |
837 | } | |
838 | ||
262c3825 | 839 | static int __init sram_proc_init(void) |
bc61b4e6 MF |
840 | { |
841 | struct proc_dir_entry *ptr; | |
842 | ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL); | |
843 | if (!ptr) { | |
844 | printk(KERN_WARNING "unable to create /proc/sram\n"); | |
845 | return -1; | |
846 | } | |
262c3825 | 847 | ptr->read_proc = sram_proc_read; |
bc61b4e6 MF |
848 | return 0; |
849 | } | |
262c3825 | 850 | late_initcall(sram_proc_init); |
bc61b4e6 | 851 | #endif |