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