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
tf_sram_slice_2_str(enum tf_sram_slice_size slice_size)102 *tf_sram_slice_2_str(enum tf_sram_slice_size slice_size)
103 {
104 switch (slice_size) {
105 case TF_SRAM_SLICE_SIZE_8B:
106 return "8B slice";
107 case TF_SRAM_SLICE_SIZE_16B:
108 return "16B slice";
109 case TF_SRAM_SLICE_SIZE_32B:
110 return "32B slice";
111 case TF_SRAM_SLICE_SIZE_64B:
112 return "64B slice";
113 case TF_SRAM_SLICE_SIZE_128B:
114 return "128B slice";
115 default:
116 return "Invalid slice size";
117 }
118 }
119
120 /**
121 * Get bank in string format
122 */
123 const char
tf_sram_bank_2_str(enum tf_sram_bank_id bank_id)124 *tf_sram_bank_2_str(enum tf_sram_bank_id bank_id)
125 {
126 switch (bank_id) {
127 case TF_SRAM_BANK_ID_0:
128 return "bank_0";
129 case TF_SRAM_BANK_ID_1:
130 return "bank_1";
131 case TF_SRAM_BANK_ID_2:
132 return "bank_2";
133 case TF_SRAM_BANK_ID_3:
134 return "bank_3";
135 default:
136 return "Invalid bank_id";
137 }
138 }
139
140 /**
141 * TF SRAM get slice list
142 */
143 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)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 *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
tf_sram_block_id_2_offset(enum tf_sram_bank_id bank_id,uint16_t block_id,uint16_t * offset)170 tf_sram_block_id_2_offset(enum tf_sram_bank_id bank_id, uint16_t block_id,
171 uint16_t *offset)
172 {
173 *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
tf_sram_offset_2_block_id(enum tf_sram_bank_id bank_id,uint16_t offset,uint16_t * block_id,uint16_t * slice_offset)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 *slice_offset = offset & 0xf;
184 *block_id = ((offset & ~0xf) >> 3) -
185 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
tf_sram_find_block(uint16_t block_id,struct tf_sram_slice_list * slice_list)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 cnt = slice_list->cnt;
198 block = slice_list->head;
199
200 while (cnt > 0 && block) {
201 if (block->block_id == block_id)
202 return block;
203 block = block->next;
204 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
tf_sram_get_next_block(struct tf_sram_block * block)215 *tf_sram_get_next_block(struct tf_sram_block *block)
216 {
217 struct tf_sram_block *nblock;
218
219 if (block != NULL)
220 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
tf_sram_free_slice(enum tf_sram_slice_size slice_size,uint16_t slice_offset,struct tf_sram_block * block,bool * block_is_empty)231 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 TF_CHECK_PARMS2(block, block_is_empty);
240
241 switch (slice_size) {
242 case TF_SRAM_SLICE_SIZE_8B:
243 shift = slice_offset >> 0;
244 assert(shift < 16);
245 slice_mask = 1 << shift;
246 break;
247
248 case TF_SRAM_SLICE_SIZE_16B:
249 shift = slice_offset >> 1;
250 assert(shift < 8);
251 slice_mask = 1 << shift;
252 break;
253
254 case TF_SRAM_SLICE_SIZE_32B:
255 shift = slice_offset >> 2;
256 assert(shift < 4);
257 slice_mask = 1 << shift;
258 break;
259
260 case TF_SRAM_SLICE_SIZE_64B:
261 shift = slice_offset >> 3;
262 assert(shift < 2);
263 slice_mask = 1 << shift;
264 break;
265
266 case TF_SRAM_SLICE_SIZE_128B:
267 default:
268 shift = slice_offset >> 0;
269 assert(shift < 1);
270 slice_mask = 1 << shift;
271 break;
272 }
273
274 if ((block->in_use_mask & slice_mask) == 0) {
275 rc = -EINVAL;
276 TFP_DRV_LOG(ERR, "block_id(0x%x) slice(%d) was not allocated\n",
277 block->block_id, slice_offset);
278 return rc;
279 }
280
281 block->in_use_mask &= ~slice_mask;
282
283 if (block->in_use_mask == 0)
284 *block_is_empty = true;
285 else
286 *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
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)298 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 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 mask = block->in_use_mask;
338
339 for (i = 0; i < max_slices; i++) {
340 if ((mask & 1) == 0) {
341 free_id = i;
342 block->in_use_mask |= 1 << free_id;
343 break;
344 }
345 mask = mask >> 1;
346 }
347
348 if (block->in_use_mask == full_mask)
349 *block_is_full = true;
350 else
351 *block_is_full = false;
352
353 if (free_id >= 0) {
354 *slice_offset = free_id << shift;
355 rc = 0;
356 } else {
357 *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
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)370 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 TF_CHECK_PARMS2(block, is_allocated);
380
381 *is_allocated = false;
382
383 switch (slice_size) {
384 case TF_SRAM_SLICE_SIZE_8B:
385 shift = slice_offset >> 0;
386 assert(shift < 16);
387 slice_mask = 1 << shift;
388 break;
389
390 case TF_SRAM_SLICE_SIZE_16B:
391 shift = slice_offset >> 1;
392 assert(shift < 8);
393 slice_mask = 1 << shift;
394 break;
395
396 case TF_SRAM_SLICE_SIZE_32B:
397 shift = slice_offset >> 2;
398 assert(shift < 4);
399 slice_mask = 1 << shift;
400 break;
401
402 case TF_SRAM_SLICE_SIZE_64B:
403 shift = slice_offset >> 3;
404 assert(shift < 2);
405 slice_mask = 1 << shift;
406 break;
407
408 case TF_SRAM_SLICE_SIZE_128B:
409 default:
410 shift = slice_offset >> 0;
411 assert(shift < 1);
412 slice_mask = 1 << shift;
413 break;
414 }
415
416 if ((block->in_use_mask & slice_mask) == 0) {
417 TFP_DRV_LOG(ERR, "block_id(0x%x) slice(%d) was not allocated\n",
418 block->block_id, slice_offset);
419 *is_allocated = false;
420 } else {
421 *is_allocated = true;
422 }
423
424 return rc;
425 }
426
427 /**
428 * Get the block count
429 */
430 static uint32_t
tf_sram_get_block_cnt(struct tf_sram_slice_list * slice_list)431 tf_sram_get_block_cnt(struct tf_sram_slice_list *slice_list)
432 {
433 return slice_list->cnt;
434 }
435
436 /**
437 * Free a block data structure - does not free to the RM
438 */
439 static void
tf_sram_free_block(struct tf_sram_slice_list * slice_list,struct tf_sram_block * block)440 tf_sram_free_block(struct tf_sram_slice_list *slice_list,
441 struct tf_sram_block *block)
442 {
443 if (slice_list->head == block && slice_list->tail == block) {
444 slice_list->head = NULL;
445 slice_list->tail = NULL;
446 } else if (slice_list->head == block) {
447 slice_list->head = block->next;
448 slice_list->head->prev = NULL;
449 } else if (slice_list->tail == block) {
450 slice_list->tail = block->prev;
451 slice_list->tail->next = NULL;
452 } else {
453 block->prev->next = block->next;
454 block->next->prev = block->prev;
455 }
456 tfp_free(block);
457 slice_list->cnt--;
458 }
459 /**
460 * Free the entire slice_list
461 */
462 static void
tf_sram_free_slice_list(struct tf_sram_slice_list * slice_list)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 block = slice_list->head;
470
471 for (i = 0; i < block_cnt; i++) {
472 nblock = block->next;
473 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
tf_sram_alloc_block(struct tf_sram_slice_list * slice_list,uint16_t block_id)482 *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 cparms.nitems = 1;
490 cparms.size = sizeof(struct tf_sram_block);
491 cparms.alignment = 0;
492 rc = tfp_calloc(&cparms);
493 if (rc) {
494 /* Log error */
495 TFP_DRV_LOG(ERR,
496 "Failed to allocate block, rc:%s\n",
497 strerror(-rc));
498 return NULL;
499 }
500 block = (struct tf_sram_block *)cparms.mem_va;
501 block->block_id = block_id;
502
503 if (slice_list->head == NULL) {
504 slice_list->head = block;
505 slice_list->tail = block;
506 block->next = NULL;
507 block->prev = NULL;
508 } else {
509 block->next = slice_list->head;
510 block->prev = NULL;
511 block->next->prev = block;
512 slice_list->head = block->next->prev;
513 }
514 slice_list->cnt++;
515 return block;
516 }
517
518 /**
519 * Find the first not full block in the slice list
520 */
521 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)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 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 *first_not_full_block = NULL;
553
554 while (block) {
555 mask = block->in_use_mask & slice_mask;
556 if (mask != slice_mask) {
557 *first_not_full_block = block;
558 break;
559 }
560 block = block->next;
561 }
562 }
563 static void
tf_sram_dump_block(struct tf_sram_block * block)564 tf_sram_dump_block(struct tf_sram_block *block)
565 {
566 TFP_DRV_LOG(INFO, "block_id(0x%x) in_use_mask(0x%04x)\n",
567 block->block_id,
568 block->in_use_mask);
569 }
570
571 /**********************
572 * External functions
573 **********************/
574 int
tf_sram_mgr_bind(void ** sram_handle)575 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 TF_CHECK_PARMS1(sram_handle);
582
583 cparms.nitems = 1;
584 cparms.size = sizeof(struct tf_sram);
585 cparms.alignment = 0;
586 rc = tfp_calloc(&cparms);
587 if (rc) {
588 /* Log error */
589 TFP_DRV_LOG(ERR,
590 "Failed to allocate SRAM mgmt data, rc:%s\n",
591 strerror(-rc));
592 return rc;
593 }
594 sram = (struct tf_sram *)cparms.mem_va;
595 *sram_handle = sram;
596 return rc;
597 }
598
599 int
tf_sram_mgr_unbind(void * sram_handle)600 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 TF_CHECK_PARMS1(sram_handle);
610
611 sram = (struct tf_sram *)sram_handle;
612
613 for (dir = 0; dir < TF_DIR_MAX; dir++) {
614 /* For each bank
615 */
616 for (bank_id = TF_SRAM_BANK_ID_0;
617 bank_id < TF_SRAM_BANK_ID_MAX;
618 bank_id++) {
619 /* For each slice size
620 */
621 for (slice_size = TF_SRAM_SLICE_SIZE_8B;
622 slice_size < TF_SRAM_SLICE_SIZE_MAX;
623 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 if (tf_sram_get_block_cnt(slice_list))
635 tf_sram_free_slice_list(slice_list);
636 }
637 }
638 }
639
640 tfp_free(sram);
641 sram_handle = NULL;
642
643 /* Freeing of the RM resources is handled by the table manager */
644 return rc;
645 }
646
tf_sram_mgr_alloc(void * sram_handle,struct tf_sram_mgr_alloc_parms * parms)647 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 uint16_t block_id, slice_offset = 0;
654 uint32_t index, next_index;
655 struct tf_sram_block *block;
656 struct tf_rm_allocate_parms aparms = { 0 };
657 struct tf_rm_free_parms fparms = { 0 };
658 bool block_is_full;
659 uint16_t block_offset;
660
661 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 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 if (!slice_list->first_not_full_block) {
680 /* Allocate and insert a new block
681 */
682 aparms.index = &index;
683 aparms.subtype = parms->tbl_type;
684 aparms.rm_db = parms->rm_db;
685 rc = tf_rm_allocate(&aparms);
686 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 aparms.index = &next_index;
693 rc = tf_rm_allocate(&aparms);
694 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 if (unlikely(index + 1 != next_index)) {
701 fparms.index = index;
702 fparms.subtype = parms->tbl_type;
703 fparms.rm_db = parms->rm_db;
704 tf_rm_free(&fparms);
705 fparms.index = next_index;
706 tf_rm_free(&fparms);
707 TFP_DRV_LOG(ERR,
708 "Could not allocate two sequential 64B blocks\n");
709 return -ENOMEM;
710 }
711 block_id = index;
712 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 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 tf_sram_find_first_not_full_block(slice_list,
728 parms->slice_size,
729 &slice_list->first_not_full_block);
730
731 tf_sram_block_id_2_offset(parms->bank_id, block->block_id,
732 &block_offset);
733
734 *parms->sram_offset = block_offset + slice_offset;
735 return rc;
736 }
737
738 int
tf_sram_mgr_free(void * sram_handle,struct tf_sram_mgr_free_parms * parms)739 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 struct tf_rm_free_parms fparms = { 0 };
749
750 TF_CHECK_PARMS2(sram_handle, parms);
751
752 sram = (struct tf_sram *)sram_handle;
753
754 /* Check the current slice list
755 */
756 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 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 block = tf_sram_find_block(block_id, slice_list);
774 if (block == NULL) {
775 TFP_DRV_LOG(ERR, "block not found 0x%x\n", block_id);
776 return rc;
777 }
778
779 /* If found, search for the matching SRAM slice in use.
780 */
781 rc = tf_sram_free_slice(parms->slice_size, slice_offset,
782 block, &block_is_empty);
783 if (rc) {
784 TFP_DRV_LOG(ERR, "Error freeing slice (%s)\n", strerror(-rc));
785 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 if (parms->tbl_type == TF_TBL_TYPE_ACT_STATS_64) {
794 uint8_t data[8] = { 0 };
795 uint16_t hcapi_type = 0;
796 struct tf_rm_get_hcapi_parms hparms = { 0 };
797
798 /* Get the hcapi type */
799 hparms.rm_db = parms->rm_db;
800 hparms.subtype = parms->tbl_type;
801 hparms.hcapi_type = &hcapi_type;
802 rc = tf_rm_get_hcapi_type(&hparms);
803 if (rc) {
804 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 return rc;
810 }
811 /* Clear the counter
812 */
813 rc = tf_msg_set_tbl_entry(parms->tfp,
814 parms->dir,
815 hcapi_type,
816 sizeof(data),
817 data,
818 parms->sram_offset);
819 if (rc) {
820 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 return rc;
826 }
827 }
828 #endif
829 /* If the block is empty, free the block to the RM
830 */
831 if (block_is_empty) {
832 fparms.rm_db = parms->rm_db;
833 fparms.subtype = parms->tbl_type;
834 fparms.index = block_id;
835 rc = tf_rm_free(&fparms);
836
837 if (rc) {
838 TFP_DRV_LOG(ERR, "Free block_id(%d) failed error(%s)\n",
839 block_id, strerror(-rc));
840 }
841 fparms.index = block_id + 1;
842 rc = tf_rm_free(&fparms);
843
844 if (rc) {
845 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 tf_sram_free_block(slice_list, block);
850
851 /* Clear the not full block to set it again */
852 slice_list->first_not_full_block = NULL;
853 }
854 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 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
tf_sram_mgr_dump(void * sram_handle,struct tf_sram_mgr_dump_parms * parms)865 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 TF_CHECK_PARMS2(sram_handle, parms);
875
876 sram = (struct tf_sram *)sram_handle;
877
878 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 if (slice_list->cnt || slice_list->first_not_full_block) {
884 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 TFP_DRV_LOG(INFO, "block_cnt(%d)\n", block_cnt);
891 if (slice_list->first_not_full_block)
892 TFP_DRV_LOG(INFO, "first_not_full_block(0x%x)\n",
893 slice_list->first_not_full_block->block_id);
894 block = slice_list->head;
895 for (i = 0; i < block_cnt; i++) {
896 tf_sram_dump_block(block);
897 block = tf_sram_get_next_block(block);
898 }
899 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 */
tf_sram_mgr_is_allocated(void * sram_handle,struct tf_sram_mgr_is_allocated_parms * parms)919 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 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 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 if (!slice_list->cnt) {
947 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 parms->is_allocated = false;
953 goto done;
954 }
955
956 /* Determine the block id and slice offset from the SRAM offset
957 */
958 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 if (block == NULL) {
965 TFP_DRV_LOG(ERR, "block not found in list 0x%x\n",
966 parms->sram_offset);
967 parms->is_allocated = false;
968 goto done;
969 }
970
971 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 }
978