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