xref: /dpdk/drivers/net/bnxt/tf_core/tf_sram_mgr.c (revision 97435d7906d7706e39e5c3dfefa5e09d7de7f733)
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