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