Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : : #include <stdlib.h>
6 : : #include <stdio.h>
7 : : #include "tf_sram_mgr.h"
8 : : #include "tf_core.h"
9 : : #include "tf_rm.h"
10 : : #include "tf_common.h"
11 : : #include "assert.h"
12 : : #include "tf_util.h"
13 : : #include "tfp.h"
14 : : #if (STATS_CLEAR_ON_READ_SUPPORT == 0)
15 : : #include "tf_msg.h"
16 : : #endif
17 : : /***************************
18 : : * Internal Data Structures
19 : : ***************************/
20 : :
21 : : /**
22 : : * TF SRAM block info
23 : : *
24 : : * Contains all the information about a particular 128B SRAM
25 : : * block and the slices within it.
26 : : */
27 : : struct tf_sram_block {
28 : : /* Previous block
29 : : */
30 : : struct tf_sram_block *prev;
31 : : /* Next block
32 : : */
33 : : struct tf_sram_block *next;
34 : :
35 : : /** Bitmap indicating which slices are in use
36 : : * If a bit is set, it indicates the slice
37 : : * in the row is in use.
38 : : */
39 : : uint16_t in_use_mask;
40 : :
41 : : /** Block id - this is a 128B offset
42 : : */
43 : : uint16_t block_id;
44 : : };
45 : :
46 : : /**
47 : : * TF SRAM block list
48 : : *
49 : : * List of 128B SRAM blocks used for fixed size slices (8, 16, 32, 64B, 128B)
50 : : */
51 : : struct tf_sram_slice_list {
52 : : /** Pointer to head of linked list of blocks.
53 : : */
54 : : struct tf_sram_block *head;
55 : :
56 : : /** Pointer to tail of linked list of blocks.
57 : : */
58 : : struct tf_sram_block *tail;
59 : :
60 : : /** Total count of blocks
61 : : */
62 : : uint32_t cnt;
63 : :
64 : : /** First non-full block in the list
65 : : */
66 : : struct tf_sram_block *first_not_full_block;
67 : :
68 : : /** Entry slice size for this list
69 : : */
70 : : enum tf_sram_slice_size size;
71 : : };
72 : :
73 : : /**
74 : : * TF SRAM bank info consists of lists of different slice sizes per bank
75 : : */
76 : : struct tf_sram_bank_info {
77 : : struct tf_sram_slice_list slice[TF_SRAM_SLICE_SIZE_MAX];
78 : : };
79 : :
80 : : /**
81 : : * SRAM banks consist of SRAM bank information
82 : : */
83 : : struct tf_sram_bank {
84 : : struct tf_sram_bank_info bank[TF_SRAM_BANK_ID_MAX];
85 : : };
86 : :
87 : : /**
88 : : * SRAM banks consist of SRAM bank information
89 : : */
90 : : struct tf_sram {
91 : : struct tf_sram_bank dir[TF_DIR_MAX];
92 : : };
93 : :
94 : : /**********************
95 : : * Internal functions
96 : : **********************/
97 : :
98 : : /**
99 : : * Get slice size in string format
100 : : */
101 : : const char
102 : 0 : *tf_sram_slice_2_str(enum tf_sram_slice_size slice_size)
103 : : {
104 [ # # # # : 0 : switch (slice_size) {
# # ]
105 : : case TF_SRAM_SLICE_SIZE_8B:
106 : : return "8B slice";
107 : 0 : case TF_SRAM_SLICE_SIZE_16B:
108 : 0 : return "16B slice";
109 : 0 : case TF_SRAM_SLICE_SIZE_32B:
110 : 0 : return "32B slice";
111 : 0 : case TF_SRAM_SLICE_SIZE_64B:
112 : 0 : return "64B slice";
113 : 0 : case TF_SRAM_SLICE_SIZE_128B:
114 : 0 : return "128B slice";
115 : 0 : default:
116 : 0 : return "Invalid slice size";
117 : : }
118 : : }
119 : :
120 : : /**
121 : : * Get bank in string format
122 : : */
123 : : const char
124 : 0 : *tf_sram_bank_2_str(enum tf_sram_bank_id bank_id)
125 : : {
126 [ # # # # : 0 : switch (bank_id) {
# ]
127 : : case TF_SRAM_BANK_ID_0:
128 : : return "bank_0";
129 : 0 : case TF_SRAM_BANK_ID_1:
130 : 0 : return "bank_1";
131 : 0 : case TF_SRAM_BANK_ID_2:
132 : 0 : return "bank_2";
133 : 0 : case TF_SRAM_BANK_ID_3:
134 : 0 : return "bank_3";
135 : 0 : default:
136 : 0 : return "Invalid bank_id";
137 : : }
138 : : }
139 : :
140 : : /**
141 : : * TF SRAM get slice list
142 : : */
143 : : static int
144 : : tf_sram_get_slice_list(struct tf_sram *sram,
145 : : struct tf_sram_slice_list **slice_list,
146 : : enum tf_sram_slice_size slice_size,
147 : : enum tf_dir dir,
148 : : enum tf_sram_bank_id bank_id)
149 : : {
150 : : int rc = 0;
151 : :
152 : : TF_CHECK_PARMS2(sram, slice_list);
153 : :
154 : 0 : *slice_list = &sram->dir[dir].bank[bank_id].slice[slice_size];
155 : :
156 : : return rc;
157 : : }
158 : :
159 : : uint16_t tf_sram_bank_2_base_offset[TF_SRAM_BANK_ID_MAX] = {
160 : : 0,
161 : : 2048,
162 : : 4096,
163 : : 6144
164 : : };
165 : :
166 : : /**
167 : : * Translate a block id and bank_id to an 8B offset
168 : : */
169 : : static void
170 : : tf_sram_block_id_2_offset(enum tf_sram_bank_id bank_id, uint16_t block_id,
171 : : uint16_t *offset)
172 : : {
173 : 0 : *offset = (block_id + tf_sram_bank_2_base_offset[bank_id]) << 3;
174 : : }
175 : :
176 : : /**
177 : : * Translates an 8B offset and bank_id to a block_id
178 : : */
179 : : static void
180 : : tf_sram_offset_2_block_id(enum tf_sram_bank_id bank_id, uint16_t offset,
181 : : uint16_t *block_id, uint16_t *slice_offset)
182 : : {
183 : 0 : *slice_offset = offset & 0xf;
184 : 0 : *block_id = ((offset & ~0xf) >> 3) -
185 : 0 : tf_sram_bank_2_base_offset[bank_id];
186 : : }
187 : :
188 : : /**
189 : : * Find a matching block_id within the slice list
190 : : */
191 : : static struct tf_sram_block
192 : : *tf_sram_find_block(uint16_t block_id, struct tf_sram_slice_list *slice_list)
193 : : {
194 : : uint32_t cnt;
195 : : struct tf_sram_block *block;
196 : :
197 : 0 : cnt = slice_list->cnt;
198 : 0 : block = slice_list->head;
199 : :
200 [ # # # # ]: 0 : while (cnt > 0 && block) {
201 [ # # # # ]: 0 : if (block->block_id == block_id)
202 : : return block;
203 : 0 : block = block->next;
204 : 0 : cnt--;
205 : : }
206 : : return NULL;
207 : : }
208 : :
209 : : /**
210 : : * Given the current block get the next block within the slice list
211 : : *
212 : : * List is not changed.
213 : : */
214 : : static struct tf_sram_block
215 : : *tf_sram_get_next_block(struct tf_sram_block *block)
216 : : {
217 : : struct tf_sram_block *nblock;
218 : :
219 [ # # ]: 0 : if (block != NULL)
220 : 0 : nblock = block->next;
221 : : else
222 : : nblock = NULL;
223 : : return nblock;
224 : : }
225 : :
226 : : /**
227 : : * Free an allocated slice from a block and if the block is empty,
228 : : * return an indication so that the block can be freed.
229 : : */
230 : : static int
231 : 0 : tf_sram_free_slice(enum tf_sram_slice_size slice_size,
232 : : uint16_t slice_offset, struct tf_sram_block *block,
233 : : bool *block_is_empty)
234 : : {
235 : : int rc = 0;
236 : : uint16_t shift;
237 : : uint16_t slice_mask = 0;
238 : :
239 [ # # ]: 0 : TF_CHECK_PARMS2(block, block_is_empty);
240 : :
241 [ # # # # : 0 : switch (slice_size) {
# ]
242 : 0 : case TF_SRAM_SLICE_SIZE_8B:
243 : : shift = slice_offset >> 0;
244 [ # # ]: 0 : assert(shift < 16);
245 : 0 : slice_mask = 1 << shift;
246 : 0 : break;
247 : :
248 : 0 : case TF_SRAM_SLICE_SIZE_16B:
249 : 0 : shift = slice_offset >> 1;
250 [ # # ]: 0 : assert(shift < 8);
251 : 0 : slice_mask = 1 << shift;
252 : 0 : break;
253 : :
254 : 0 : case TF_SRAM_SLICE_SIZE_32B:
255 : 0 : shift = slice_offset >> 2;
256 [ # # ]: 0 : assert(shift < 4);
257 : 0 : slice_mask = 1 << shift;
258 : 0 : break;
259 : :
260 : 0 : case TF_SRAM_SLICE_SIZE_64B:
261 : 0 : shift = slice_offset >> 3;
262 [ # # ]: 0 : assert(shift < 2);
263 : 0 : slice_mask = 1 << shift;
264 : 0 : break;
265 : :
266 : 0 : case TF_SRAM_SLICE_SIZE_128B:
267 : : default:
268 : : shift = slice_offset >> 0;
269 [ # # ]: 0 : assert(shift < 1);
270 : : slice_mask = 1 << shift;
271 : : break;
272 : : }
273 : :
274 [ # # ]: 0 : if ((block->in_use_mask & slice_mask) == 0) {
275 : : rc = -EINVAL;
276 : 0 : TFP_DRV_LOG(ERR, "block_id(0x%x) slice(%d) was not allocated\n",
277 : : block->block_id, slice_offset);
278 : 0 : return rc;
279 : : }
280 : :
281 : 0 : block->in_use_mask &= ~slice_mask;
282 : :
283 [ # # ]: 0 : if (block->in_use_mask == 0)
284 : 0 : *block_is_empty = true;
285 : : else
286 : 0 : *block_is_empty = false;
287 : :
288 : : return rc;
289 : : }
290 : :
291 : : /**
292 : : * TF SRAM get next slice
293 : : *
294 : : * Gets the next slice_offset available in the block
295 : : * and updates the in_use_mask.
296 : : */
297 : : static int
298 : 0 : tf_sram_get_next_slice_in_block(struct tf_sram_block *block,
299 : : enum tf_sram_slice_size slice_size,
300 : : uint16_t *slice_offset,
301 : : bool *block_is_full)
302 : : {
303 : : int rc, free_id = -1;
304 : : uint16_t shift, max_slices, mask, i, full_mask;
305 : :
306 [ # # # # ]: 0 : TF_CHECK_PARMS3(block, slice_offset, block_is_full);
307 : :
308 : : switch (slice_size) {
309 : : case TF_SRAM_SLICE_SIZE_8B:
310 : : shift = 0;
311 : : max_slices = 16;
312 : : full_mask = 0xffff;
313 : : break;
314 : : case TF_SRAM_SLICE_SIZE_16B:
315 : : shift = 1;
316 : : max_slices = 8;
317 : : full_mask = 0xff;
318 : : break;
319 : : case TF_SRAM_SLICE_SIZE_32B:
320 : : shift = 2;
321 : : max_slices = 4;
322 : : full_mask = 0xf;
323 : : break;
324 : : case TF_SRAM_SLICE_SIZE_64B:
325 : : shift = 3;
326 : : max_slices = 2;
327 : : full_mask = 0x3;
328 : : break;
329 : : case TF_SRAM_SLICE_SIZE_128B:
330 : : default:
331 : : shift = 0;
332 : : max_slices = 1;
333 : : full_mask = 1;
334 : : break;
335 : : }
336 : :
337 : 0 : mask = block->in_use_mask;
338 : :
339 [ # # ]: 0 : for (i = 0; i < max_slices; i++) {
340 [ # # ]: 0 : if ((mask & 1) == 0) {
341 : 0 : free_id = i;
342 : 0 : block->in_use_mask |= 1 << free_id;
343 : 0 : break;
344 : : }
345 : 0 : mask = mask >> 1;
346 : : }
347 : :
348 [ # # ]: 0 : if (block->in_use_mask == full_mask)
349 : 0 : *block_is_full = true;
350 : : else
351 : 0 : *block_is_full = false;
352 : :
353 [ # # ]: 0 : if (free_id >= 0) {
354 : 0 : *slice_offset = free_id << shift;
355 : : rc = 0;
356 : : } else {
357 : 0 : *slice_offset = 0;
358 : : rc = -ENOMEM;
359 : : }
360 : :
361 : : return rc;
362 : : }
363 : :
364 : : /**
365 : : * TF SRAM get indication as to whether the slice offset is
366 : : * allocated in the block.
367 : : *
368 : : */
369 : : static int
370 : 0 : tf_sram_is_slice_allocated_in_block(struct tf_sram_block *block,
371 : : enum tf_sram_slice_size slice_size,
372 : : uint16_t slice_offset,
373 : : bool *is_allocated)
374 : : {
375 : : int rc = 0;
376 : : uint16_t shift;
377 : : uint16_t slice_mask = 0;
378 : :
379 [ # # ]: 0 : TF_CHECK_PARMS2(block, is_allocated);
380 : :
381 : 0 : *is_allocated = false;
382 : :
383 [ # # # # : 0 : switch (slice_size) {
# ]
384 : 0 : case TF_SRAM_SLICE_SIZE_8B:
385 : : shift = slice_offset >> 0;
386 [ # # ]: 0 : assert(shift < 16);
387 : 0 : slice_mask = 1 << shift;
388 : 0 : break;
389 : :
390 : 0 : case TF_SRAM_SLICE_SIZE_16B:
391 : 0 : shift = slice_offset >> 1;
392 [ # # ]: 0 : assert(shift < 8);
393 : 0 : slice_mask = 1 << shift;
394 : 0 : break;
395 : :
396 : 0 : case TF_SRAM_SLICE_SIZE_32B:
397 : 0 : shift = slice_offset >> 2;
398 [ # # ]: 0 : assert(shift < 4);
399 : 0 : slice_mask = 1 << shift;
400 : 0 : break;
401 : :
402 : 0 : case TF_SRAM_SLICE_SIZE_64B:
403 : 0 : shift = slice_offset >> 3;
404 [ # # ]: 0 : assert(shift < 2);
405 : 0 : slice_mask = 1 << shift;
406 : 0 : break;
407 : :
408 : 0 : case TF_SRAM_SLICE_SIZE_128B:
409 : : default:
410 : : shift = slice_offset >> 0;
411 [ # # ]: 0 : assert(shift < 1);
412 : : slice_mask = 1 << shift;
413 : : break;
414 : : }
415 : :
416 [ # # ]: 0 : if ((block->in_use_mask & slice_mask) == 0) {
417 : 0 : TFP_DRV_LOG(ERR, "block_id(0x%x) slice(%d) was not allocated\n",
418 : : block->block_id, slice_offset);
419 : 0 : *is_allocated = false;
420 : : } else {
421 : 0 : *is_allocated = true;
422 : : }
423 : :
424 : : return rc;
425 : : }
426 : :
427 : : /**
428 : : * Get the block count
429 : : */
430 : : static uint32_t
431 : : tf_sram_get_block_cnt(struct tf_sram_slice_list *slice_list)
432 : : {
433 : 0 : return slice_list->cnt;
434 : : }
435 : :
436 : : /**
437 : : * Free a block data structure - does not free to the RM
438 : : */
439 : : static void
440 : 0 : tf_sram_free_block(struct tf_sram_slice_list *slice_list,
441 : : struct tf_sram_block *block)
442 : : {
443 [ # # # # ]: 0 : if (slice_list->head == block && slice_list->tail == block) {
444 : 0 : slice_list->head = NULL;
445 : 0 : slice_list->tail = NULL;
446 [ # # ]: 0 : } else if (slice_list->head == block) {
447 : 0 : slice_list->head = block->next;
448 : 0 : slice_list->head->prev = NULL;
449 [ # # ]: 0 : } else if (slice_list->tail == block) {
450 : 0 : slice_list->tail = block->prev;
451 : 0 : slice_list->tail->next = NULL;
452 : : } else {
453 : 0 : block->prev->next = block->next;
454 : 0 : block->next->prev = block->prev;
455 : : }
456 : 0 : tfp_free(block);
457 : 0 : slice_list->cnt--;
458 : 0 : }
459 : : /**
460 : : * Free the entire slice_list
461 : : */
462 : : static void
463 : : tf_sram_free_slice_list(struct tf_sram_slice_list *slice_list)
464 : : {
465 : : uint32_t i, block_cnt;
466 : : struct tf_sram_block *nblock, *block;
467 : :
468 : : block_cnt = tf_sram_get_block_cnt(slice_list);
469 : 0 : block = slice_list->head;
470 : :
471 [ # # ]: 0 : for (i = 0; i < block_cnt; i++) {
472 : 0 : nblock = block->next;
473 : 0 : tf_sram_free_block(slice_list, block);
474 : : block = nblock;
475 : : }
476 : : }
477 : :
478 : : /**
479 : : * Allocate a single SRAM block from memory and add it to the slice list
480 : : */
481 : : static struct tf_sram_block
482 : 0 : *tf_sram_alloc_block(struct tf_sram_slice_list *slice_list,
483 : : uint16_t block_id)
484 : : {
485 : : struct tf_sram_block *block;
486 : : struct tfp_calloc_parms cparms;
487 : : int rc;
488 : :
489 : 0 : cparms.nitems = 1;
490 : 0 : cparms.size = sizeof(struct tf_sram_block);
491 : 0 : cparms.alignment = 0;
492 : 0 : rc = tfp_calloc(&cparms);
493 [ # # ]: 0 : if (rc) {
494 : : /* Log error */
495 : 0 : TFP_DRV_LOG(ERR,
496 : : "Failed to allocate block, rc:%s\n",
497 : : strerror(-rc));
498 : 0 : return NULL;
499 : : }
500 : 0 : block = (struct tf_sram_block *)cparms.mem_va;
501 : 0 : block->block_id = block_id;
502 : :
503 [ # # ]: 0 : if (slice_list->head == NULL) {
504 : 0 : slice_list->head = block;
505 : 0 : slice_list->tail = block;
506 : 0 : block->next = NULL;
507 : 0 : block->prev = NULL;
508 : : } else {
509 : 0 : block->next = slice_list->head;
510 : 0 : block->prev = NULL;
511 : 0 : block->next->prev = block;
512 : 0 : slice_list->head = block->next->prev;
513 : : }
514 : 0 : slice_list->cnt++;
515 : 0 : return block;
516 : : }
517 : :
518 : : /**
519 : : * Find the first not full block in the slice list
520 : : */
521 : : static void
522 : : tf_sram_find_first_not_full_block(struct tf_sram_slice_list *slice_list,
523 : : enum tf_sram_slice_size slice_size,
524 : : struct tf_sram_block **first_not_full_block)
525 : : {
526 : 0 : struct tf_sram_block *block = slice_list->head;
527 : : uint16_t slice_mask, mask;
528 : :
529 : : switch (slice_size) {
530 : : case TF_SRAM_SLICE_SIZE_8B:
531 : : slice_mask = 0xffff;
532 : : break;
533 : :
534 : : case TF_SRAM_SLICE_SIZE_16B:
535 : : slice_mask = 0xff;
536 : : break;
537 : :
538 : : case TF_SRAM_SLICE_SIZE_32B:
539 : : slice_mask = 0xf;
540 : : break;
541 : :
542 : : case TF_SRAM_SLICE_SIZE_64B:
543 : : slice_mask = 0x3;
544 : : break;
545 : :
546 : : case TF_SRAM_SLICE_SIZE_128B:
547 : : default:
548 : : slice_mask = 0x1;
549 : : break;
550 : : }
551 : :
552 : 0 : *first_not_full_block = NULL;
553 : :
554 [ # # # # ]: 0 : while (block) {
555 : 0 : mask = block->in_use_mask & slice_mask;
556 [ # # # # ]: 0 : if (mask != slice_mask) {
557 : 0 : *first_not_full_block = block;
558 : 0 : break;
559 : : }
560 : 0 : block = block->next;
561 : : }
562 : : }
563 : : static void
564 : 0 : tf_sram_dump_block(struct tf_sram_block *block)
565 : : {
566 : 0 : TFP_DRV_LOG(INFO, "block_id(0x%x) in_use_mask(0x%04x)\n",
567 : : block->block_id,
568 : : block->in_use_mask);
569 : 0 : }
570 : :
571 : : /**********************
572 : : * External functions
573 : : **********************/
574 : : int
575 : 0 : tf_sram_mgr_bind(void **sram_handle)
576 : : {
577 : : int rc = 0;
578 : : struct tf_sram *sram;
579 : : struct tfp_calloc_parms cparms;
580 : :
581 [ # # ]: 0 : TF_CHECK_PARMS1(sram_handle);
582 : :
583 : 0 : cparms.nitems = 1;
584 : 0 : cparms.size = sizeof(struct tf_sram);
585 : 0 : cparms.alignment = 0;
586 : 0 : rc = tfp_calloc(&cparms);
587 [ # # ]: 0 : if (rc) {
588 : : /* Log error */
589 : 0 : TFP_DRV_LOG(ERR,
590 : : "Failed to allocate SRAM mgmt data, rc:%s\n",
591 : : strerror(-rc));
592 : 0 : return rc;
593 : : }
594 : 0 : sram = (struct tf_sram *)cparms.mem_va;
595 : 0 : *sram_handle = sram;
596 : 0 : return rc;
597 : : }
598 : :
599 : : int
600 : 0 : tf_sram_mgr_unbind(void *sram_handle)
601 : : {
602 : : int rc = 0;
603 : : struct tf_sram *sram;
604 : : enum tf_sram_bank_id bank_id;
605 : : enum tf_sram_slice_size slice_size;
606 : : enum tf_dir dir;
607 : : struct tf_sram_slice_list *slice_list;
608 : :
609 [ # # ]: 0 : TF_CHECK_PARMS1(sram_handle);
610 : :
611 : : sram = (struct tf_sram *)sram_handle;
612 : :
613 [ # # ]: 0 : for (dir = 0; dir < TF_DIR_MAX; dir++) {
614 : : /* For each bank
615 : : */
616 : : for (bank_id = TF_SRAM_BANK_ID_0;
617 [ # # ]: 0 : bank_id < TF_SRAM_BANK_ID_MAX;
618 : 0 : bank_id++) {
619 : : /* For each slice size
620 : : */
621 : : for (slice_size = TF_SRAM_SLICE_SIZE_8B;
622 [ # # ]: 0 : slice_size < TF_SRAM_SLICE_SIZE_MAX;
623 : 0 : slice_size++) {
624 : : rc = tf_sram_get_slice_list(sram, &slice_list,
625 : : slice_size, dir,
626 : : bank_id);
627 : : if (rc) {
628 : : /* Log error */
629 : : TFP_DRV_LOG(ERR,
630 : : "No SRAM slice list, rc:%s\n",
631 : : strerror(-rc));
632 : : return rc;
633 : : }
634 [ # # ]: 0 : if (tf_sram_get_block_cnt(slice_list))
635 : : tf_sram_free_slice_list(slice_list);
636 : : }
637 : : }
638 : : }
639 : :
640 : 0 : tfp_free(sram);
641 : : sram_handle = NULL;
642 : :
643 : : /* Freeing of the RM resources is handled by the table manager */
644 : 0 : return rc;
645 : : }
646 : :
647 : 0 : int tf_sram_mgr_alloc(void *sram_handle,
648 : : struct tf_sram_mgr_alloc_parms *parms)
649 : : {
650 : : int rc = 0;
651 : : struct tf_sram *sram;
652 : : struct tf_sram_slice_list *slice_list;
653 : 0 : uint16_t block_id, slice_offset = 0;
654 : : uint32_t index, next_index;
655 : : struct tf_sram_block *block;
656 : 0 : struct tf_rm_allocate_parms aparms = { 0 };
657 : 0 : struct tf_rm_free_parms fparms = { 0 };
658 : : bool block_is_full;
659 : : uint16_t block_offset;
660 : :
661 [ # # # # ]: 0 : TF_CHECK_PARMS3(sram_handle, parms, parms->sram_offset);
662 : :
663 : : sram = (struct tf_sram *)sram_handle;
664 : :
665 : : /* Check the current slice list
666 : : */
667 : 0 : rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
668 : : parms->dir, parms->bank_id);
669 : : if (rc) {
670 : : /* Log error */
671 : : TFP_DRV_LOG(ERR,
672 : : "No SRAM slice list, rc:%s\n",
673 : : strerror(-rc));
674 : : return rc;
675 : : }
676 : :
677 : : /* If the list is empty or all entries are full allocate a new block
678 : : */
679 [ # # ]: 0 : if (!slice_list->first_not_full_block) {
680 : : /* Allocate and insert a new block
681 : : */
682 : 0 : aparms.index = &index;
683 : 0 : aparms.subtype = parms->tbl_type;
684 : 0 : aparms.rm_db = parms->rm_db;
685 : 0 : rc = tf_rm_allocate(&aparms);
686 [ # # ]: 0 : if (rc)
687 : : return rc;
688 : : /* to support 128B block rows, we are allocating
689 : : * 2 sequential 64B blocks from RM, if they are not next to
690 : : * each other we are going to have issues
691 : : */
692 : 0 : aparms.index = &next_index;
693 : 0 : rc = tf_rm_allocate(&aparms);
694 [ # # ]: 0 : if (rc)
695 : : return rc;
696 : :
697 : : /* make sure we do get the next 64B block, else free the
698 : : * allocated indexes and return error
699 : : */
700 [ # # ]: 0 : if (unlikely(index + 1 != next_index)) {
701 : 0 : fparms.index = index;
702 : 0 : fparms.subtype = parms->tbl_type;
703 : 0 : fparms.rm_db = parms->rm_db;
704 : 0 : tf_rm_free(&fparms);
705 : 0 : fparms.index = next_index;
706 : 0 : tf_rm_free(&fparms);
707 : 0 : TFP_DRV_LOG(ERR,
708 : : "Could not allocate two sequential 64B blocks\n");
709 : 0 : return -ENOMEM;
710 : : }
711 : : block_id = index;
712 : 0 : block = tf_sram_alloc_block(slice_list, block_id);
713 : :
714 : : } else {
715 : : /* Block exists
716 : : */
717 : : block =
718 : : (struct tf_sram_block *)(slice_list->first_not_full_block);
719 : : }
720 : 0 : rc = tf_sram_get_next_slice_in_block(block,
721 : : parms->slice_size,
722 : : &slice_offset,
723 : : &block_is_full);
724 : :
725 : : /* Find the new first non-full block in the list
726 : : */
727 [ # # ]: 0 : tf_sram_find_first_not_full_block(slice_list,
728 : : parms->slice_size,
729 : : &slice_list->first_not_full_block);
730 : :
731 : 0 : tf_sram_block_id_2_offset(parms->bank_id, block->block_id,
732 : : &block_offset);
733 : :
734 : 0 : *parms->sram_offset = block_offset + slice_offset;
735 : 0 : return rc;
736 : : }
737 : :
738 : : int
739 : 0 : tf_sram_mgr_free(void *sram_handle,
740 : : struct tf_sram_mgr_free_parms *parms)
741 : : {
742 : : int rc = 0;
743 : : struct tf_sram *sram;
744 : : struct tf_sram_slice_list *slice_list;
745 : : uint16_t block_id, slice_offset;
746 : : struct tf_sram_block *block;
747 : : bool block_is_empty;
748 : 0 : struct tf_rm_free_parms fparms = { 0 };
749 : :
750 [ # # ]: 0 : TF_CHECK_PARMS2(sram_handle, parms);
751 : :
752 : : sram = (struct tf_sram *)sram_handle;
753 : :
754 : : /* Check the current slice list
755 : : */
756 : 0 : rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
757 : : parms->dir, parms->bank_id);
758 : : if (rc) {
759 : : /* Log error */
760 : : TFP_DRV_LOG(ERR,
761 : : "No SRAM slice list, rc:%s\n",
762 : : strerror(-rc));
763 : : return rc;
764 : : }
765 : :
766 : : /* Determine the block id and slice offset from the SRAM offset
767 : : */
768 : 0 : tf_sram_offset_2_block_id(parms->bank_id, parms->sram_offset, &block_id,
769 : : &slice_offset);
770 : :
771 : : /* Search the list of blocks for the matching block id
772 : : */
773 : 0 : block = tf_sram_find_block(block_id, slice_list);
774 [ # # ]: 0 : if (block == NULL) {
775 : 0 : TFP_DRV_LOG(ERR, "block not found 0x%x\n", block_id);
776 : 0 : return rc;
777 : : }
778 : :
779 : : /* If found, search for the matching SRAM slice in use.
780 : : */
781 : 0 : rc = tf_sram_free_slice(parms->slice_size, slice_offset,
782 : : block, &block_is_empty);
783 [ # # ]: 0 : if (rc) {
784 : 0 : TFP_DRV_LOG(ERR, "Error freeing slice (%s)\n", strerror(-rc));
785 : 0 : return rc;
786 : : }
787 : : #if (STATS_CLEAR_ON_READ_SUPPORT == 0)
788 : : /* If this is a counter, clear it. In the future we need to switch to
789 : : * using the special access registers on P5 to automatically clear on
790 : : * read.
791 : : */
792 : : /* If this is counter table, clear the entry on free */
793 [ # # ]: 0 : if (parms->tbl_type == TF_TBL_TYPE_ACT_STATS_64) {
794 : 0 : uint8_t data[8] = { 0 };
795 : 0 : uint16_t hcapi_type = 0;
796 : 0 : struct tf_rm_get_hcapi_parms hparms = { 0 };
797 : :
798 : : /* Get the hcapi type */
799 : 0 : hparms.rm_db = parms->rm_db;
800 : 0 : hparms.subtype = parms->tbl_type;
801 : 0 : hparms.hcapi_type = &hcapi_type;
802 : 0 : rc = tf_rm_get_hcapi_type(&hparms);
803 [ # # ]: 0 : if (rc) {
804 : 0 : TFP_DRV_LOG(ERR,
805 : : "%s, Failed type lookup, type:%s, rc:%s\n",
806 : : tf_dir_2_str(parms->dir),
807 : : tf_tbl_type_2_str(parms->tbl_type),
808 : : strerror(-rc));
809 : 0 : return rc;
810 : : }
811 : : /* Clear the counter
812 : : */
813 : 0 : rc = tf_msg_set_tbl_entry(parms->tfp,
814 : : parms->dir,
815 : : hcapi_type,
816 : : sizeof(data),
817 : : data,
818 : 0 : parms->sram_offset);
819 [ # # ]: 0 : if (rc) {
820 : 0 : TFP_DRV_LOG(ERR,
821 : : "%s, Set failed, type:%s, rc:%s\n",
822 : : tf_dir_2_str(parms->dir),
823 : : tf_tbl_type_2_str(parms->tbl_type),
824 : : strerror(-rc));
825 : 0 : return rc;
826 : : }
827 : : }
828 : : #endif
829 : : /* If the block is empty, free the block to the RM
830 : : */
831 [ # # ]: 0 : if (block_is_empty) {
832 : 0 : fparms.rm_db = parms->rm_db;
833 : 0 : fparms.subtype = parms->tbl_type;
834 : 0 : fparms.index = block_id;
835 : 0 : rc = tf_rm_free(&fparms);
836 : :
837 [ # # ]: 0 : if (rc) {
838 : 0 : TFP_DRV_LOG(ERR, "Free block_id(%d) failed error(%s)\n",
839 : : block_id, strerror(-rc));
840 : : }
841 : 0 : fparms.index = block_id + 1;
842 : 0 : rc = tf_rm_free(&fparms);
843 : :
844 [ # # ]: 0 : if (rc) {
845 : 0 : TFP_DRV_LOG(ERR, "Free next block_id(%d) failed error(%s)\n",
846 : : block_id + 1, strerror(-rc));
847 : : }
848 : : /* Free local entry regardless */
849 : 0 : tf_sram_free_block(slice_list, block);
850 : :
851 : : /* Clear the not full block to set it again */
852 : 0 : slice_list->first_not_full_block = NULL;
853 : : }
854 [ # # ]: 0 : if (slice_list->first_not_full_block)
855 : : return rc;
856 : :
857 : : /* set the non full block so it can be used in next alloc */
858 [ # # ]: 0 : tf_sram_find_first_not_full_block(slice_list,
859 : : parms->slice_size,
860 : : &slice_list->first_not_full_block);
861 : : return rc;
862 : : }
863 : :
864 : : int
865 : 0 : tf_sram_mgr_dump(void *sram_handle,
866 : : struct tf_sram_mgr_dump_parms *parms)
867 : : {
868 : : int rc = 0;
869 : : struct tf_sram *sram;
870 : : struct tf_sram_slice_list *slice_list;
871 : : uint32_t block_cnt, i;
872 : : struct tf_sram_block *block;
873 : :
874 [ # # ]: 0 : TF_CHECK_PARMS2(sram_handle, parms);
875 : :
876 : : sram = (struct tf_sram *)sram_handle;
877 : :
878 : 0 : rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
879 : : parms->dir, parms->bank_id);
880 : : if (rc)
881 : : return rc;
882 : :
883 [ # # # # ]: 0 : if (slice_list->cnt || slice_list->first_not_full_block) {
884 : 0 : TFP_DRV_LOG(INFO, "\n********** %s: %s: %s ***********\n",
885 : : tf_sram_bank_2_str(parms->bank_id),
886 : : tf_dir_2_str(parms->dir),
887 : : tf_sram_slice_2_str(parms->slice_size));
888 : :
889 : : block_cnt = tf_sram_get_block_cnt(slice_list);
890 : 0 : TFP_DRV_LOG(INFO, "block_cnt(%d)\n", block_cnt);
891 [ # # ]: 0 : if (slice_list->first_not_full_block)
892 : 0 : TFP_DRV_LOG(INFO, "first_not_full_block(0x%x)\n",
893 : : slice_list->first_not_full_block->block_id);
894 : 0 : block = slice_list->head;
895 [ # # ]: 0 : for (i = 0; i < block_cnt; i++) {
896 : 0 : tf_sram_dump_block(block);
897 : : block = tf_sram_get_next_block(block);
898 : : }
899 : 0 : TFP_DRV_LOG(INFO, "*********************************\n");
900 : : }
901 : : return rc;
902 : : }
903 : : /**
904 : : * Validate an SRAM Slice is allocated
905 : : *
906 : : * Validate whether the SRAM slice is allocated
907 : : *
908 : : * [in] sram_handle
909 : : * Pointer to SRAM handle
910 : : *
911 : : * [in] parms
912 : : * Pointer to the SRAM alloc parameters
913 : : *
914 : : * Returns
915 : : * - (0) if successful
916 : : * - (-EINVAL) on failure
917 : : *
918 : : */
919 : 0 : int tf_sram_mgr_is_allocated(void *sram_handle,
920 : : struct tf_sram_mgr_is_allocated_parms *parms)
921 : : {
922 : : int rc = 0;
923 : : struct tf_sram *sram;
924 : : struct tf_sram_slice_list *slice_list;
925 : : uint16_t block_id, slice_offset;
926 : : struct tf_sram_block *block;
927 : :
928 [ # # # # ]: 0 : TF_CHECK_PARMS3(sram_handle, parms, parms->is_allocated);
929 : :
930 : : sram = (struct tf_sram *)sram_handle;
931 : :
932 : : /* Check the current slice list
933 : : */
934 : 0 : rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
935 : : parms->dir, parms->bank_id);
936 : : if (rc) {
937 : : /* Log error */
938 : : TFP_DRV_LOG(ERR,
939 : : "No SRAM slice list, rc:%s\n",
940 : : strerror(-rc));
941 : : return rc;
942 : : }
943 : :
944 : : /* If the list is empty, then it cannot be allocated
945 : : */
946 [ # # ]: 0 : if (!slice_list->cnt) {
947 : 0 : TFP_DRV_LOG(ERR, "List is empty for %s:%s:%s\n",
948 : : tf_dir_2_str(parms->dir),
949 : : tf_sram_slice_2_str(parms->slice_size),
950 : : tf_sram_bank_2_str(parms->bank_id));
951 : :
952 : 0 : parms->is_allocated = false;
953 : 0 : goto done;
954 : : }
955 : :
956 : : /* Determine the block id and slice offset from the SRAM offset
957 : : */
958 : 0 : tf_sram_offset_2_block_id(parms->bank_id, parms->sram_offset, &block_id,
959 : : &slice_offset);
960 : :
961 : : /* Search the list of blocks for the matching block id
962 : : */
963 : : block = tf_sram_find_block(block_id, slice_list);
964 [ # # ]: 0 : if (block == NULL) {
965 : 0 : TFP_DRV_LOG(ERR, "block not found in list 0x%x\n",
966 : : parms->sram_offset);
967 : 0 : parms->is_allocated = false;
968 : 0 : goto done;
969 : : }
970 : :
971 : 0 : rc = tf_sram_is_slice_allocated_in_block(block,
972 : : parms->slice_size,
973 : : slice_offset,
974 : : parms->is_allocated);
975 : : done:
976 : : return rc;
977 : : }
|