Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2021-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <inttypes.h>
7 : : #include <signal.h>
8 : :
9 : : #include "hcapi_cfa_defs.h"
10 : :
11 : : #include "tfp.h"
12 : : #include "tf_session.h"
13 : : #include "tf_util.h"
14 : : #include "cfa_tcam_mgr.h"
15 : : #include "cfa_tcam_mgr_hwop_msg.h"
16 : : #include "cfa_tcam_mgr_device.h"
17 : : #include "cfa_tcam_mgr_session.h"
18 : : #include "cfa_tcam_mgr_p58.h"
19 : : #include "cfa_tcam_mgr_p4.h"
20 : :
21 : : #define TF_TCAM_SLICE_INVALID (-1)
22 : :
23 : : /*
24 : : * The following macros are for setting the entry status in a row entry.
25 : : * row is (struct cfa_tcam_mgr_table_rows_0 *)
26 : : */
27 : : #define ROW_ENTRY_INUSE(row, entry) ((row)->entry_inuse & (1U << (entry)))
28 : : #define ROW_ENTRY_SET(row, entry) ((row)->entry_inuse |= (1U << (entry)))
29 : : #define ROW_ENTRY_CLEAR(row, entry) ((row)->entry_inuse &= ~(1U << (entry)))
30 : : #define ROW_INUSE(row) ((row)->entry_inuse != 0)
31 : :
32 : : static struct cfa_tcam_mgr_entry_data *entry_data[TF_TCAM_MAX_SESSIONS];
33 : :
34 : : static int global_data_initialized[TF_TCAM_MAX_SESSIONS];
35 : : int cfa_tcam_mgr_max_entries[TF_TCAM_MAX_SESSIONS];
36 : :
37 : : struct cfa_tcam_mgr_table_data
38 : : cfa_tcam_mgr_tables[TF_TCAM_MAX_SESSIONS][TF_DIR_MAX][CFA_TCAM_MGR_TBL_TYPE_MAX];
39 : :
40 : : static int physical_table_types[CFA_TCAM_MGR_TBL_TYPE_MAX] = {
41 : : [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS] =
42 : : TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH,
43 : : [CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS] =
44 : : TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW,
45 : : [CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS] =
46 : : TF_TCAM_TBL_TYPE_PROF_TCAM,
47 : : [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS] =
48 : : TF_TCAM_TBL_TYPE_WC_TCAM,
49 : : [CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS] =
50 : : TF_TCAM_TBL_TYPE_SP_TCAM,
51 : : [CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS] =
52 : : TF_TCAM_TBL_TYPE_CT_RULE_TCAM,
53 : : [CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS] =
54 : : TF_TCAM_TBL_TYPE_VEB_TCAM,
55 : : [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS] =
56 : : TF_TCAM_TBL_TYPE_WC_TCAM_HIGH,
57 : : [CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS] =
58 : : TF_TCAM_TBL_TYPE_WC_TCAM_LOW,
59 : : };
60 : :
61 : : int
62 : 0 : cfa_tcam_mgr_get_phys_table_type(enum cfa_tcam_mgr_tbl_type type)
63 : : {
64 [ # # ]: 0 : if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX)
65 : 0 : assert(0);
66 : : else
67 : 0 : return physical_table_types[type];
68 : : }
69 : :
70 : : const char *
71 : 0 : cfa_tcam_mgr_tbl_2_str(enum cfa_tcam_mgr_tbl_type tcam_type)
72 : : {
73 [ # # # # : 0 : switch (tcam_type) {
# # # # #
# # # # #
# # # #
# ]
74 : : case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_AFM:
75 : : return "l2_ctxt_tcam_high AFM";
76 : 0 : case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_HIGH_APPS:
77 : 0 : return "l2_ctxt_tcam_high Apps";
78 : 0 : case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_AFM:
79 : 0 : return "l2_ctxt_tcam_low AFM";
80 : 0 : case CFA_TCAM_MGR_TBL_TYPE_L2_CTXT_TCAM_LOW_APPS:
81 : 0 : return "l2_ctxt_tcam_low Apps";
82 : 0 : case CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_AFM:
83 : 0 : return "prof_tcam AFM";
84 : 0 : case CFA_TCAM_MGR_TBL_TYPE_PROF_TCAM_APPS:
85 : 0 : return "prof_tcam Apps";
86 : 0 : case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_AFM:
87 : 0 : return "wc_tcam AFM";
88 : 0 : case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS:
89 : 0 : return "wc_tcam Apps";
90 : 0 : case CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_AFM:
91 : 0 : return "veb_tcam AFM";
92 : 0 : case CFA_TCAM_MGR_TBL_TYPE_VEB_TCAM_APPS:
93 : 0 : return "veb_tcam Apps";
94 : 0 : case CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_AFM:
95 : 0 : return "sp_tcam AFM";
96 : 0 : case CFA_TCAM_MGR_TBL_TYPE_SP_TCAM_APPS:
97 : 0 : return "sp_tcam Apps";
98 : 0 : case CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_AFM:
99 : 0 : return "ct_rule_tcam AFM";
100 : 0 : case CFA_TCAM_MGR_TBL_TYPE_CT_RULE_TCAM_APPS:
101 : 0 : return "ct_rule_tcam Apps";
102 : 0 : case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_AFM:
103 : 0 : return "wc_tcam_high AFM";
104 : 0 : case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS:
105 : 0 : return "wc_tcam_high Apps";
106 : 0 : case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_AFM:
107 : 0 : return "wc_tcam_low AFM";
108 : 0 : case CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS:
109 : 0 : return "wc_tcam_low Apps";
110 : 0 : default:
111 : 0 : return "Invalid tcam table type";
112 : : }
113 : : }
114 : :
115 : : /* key_size and slice_width are in bytes */
116 : : static int
117 : : cfa_tcam_mgr_get_num_slices(unsigned int key_size, unsigned int slice_width)
118 : : {
119 : : int num_slices = 0;
120 : :
121 : 0 : if (key_size == 0)
122 : : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
123 : :
124 : 0 : num_slices = ((key_size - 1U) / slice_width) + 1U;
125 : : /* Round up to next highest power of 2 */
126 : : /* This is necessary since, for example, 3 slices is not a valid entry
127 : : * width.
128 : : */
129 : 0 : num_slices--;
130 : : /* Repeat to maximum number of bits actually used */
131 : : /* This fills in all the bits. */
132 : 0 : num_slices |= num_slices >> 1;
133 : 0 : num_slices |= num_slices >> 2;
134 : 0 : num_slices |= num_slices >> 4;
135 : : /*
136 : : * If the maximum number of slices that are supported by the HW
137 : : * increases, then additional shifts are needed.
138 : : */
139 : 0 : num_slices++;
140 : 0 : return num_slices;
141 : : }
142 : :
143 : : static struct cfa_tcam_mgr_entry_data *
144 : : cfa_tcam_mgr_entry_get(int sess_idx, uint16_t id)
145 : : {
146 : 0 : if (id > cfa_tcam_mgr_max_entries[sess_idx])
147 : : return NULL;
148 : :
149 : 0 : return &entry_data[sess_idx][id];
150 : : }
151 : :
152 : : /* Insert an entry into the entry table */
153 : : static int
154 : 0 : cfa_tcam_mgr_entry_insert(int sess_idx, uint16_t id,
155 : : struct cfa_tcam_mgr_entry_data *entry)
156 : : {
157 [ # # ]: 0 : if (id > cfa_tcam_mgr_max_entries[sess_idx])
158 : : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
159 : :
160 : 0 : memcpy(&entry_data[sess_idx][id], entry,
161 : : sizeof(entry_data[sess_idx][id]));
162 : :
163 : 0 : return 0;
164 : : }
165 : :
166 : : /* Delete an entry from the entry table */
167 : : static int
168 : 0 : cfa_tcam_mgr_entry_delete(int sess_idx, uint16_t id)
169 : : {
170 [ # # ]: 0 : if (id > cfa_tcam_mgr_max_entries[sess_idx])
171 : : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
172 : :
173 : 0 : memset(&entry_data[sess_idx][id], 0, sizeof(entry_data[sess_idx][id]));
174 : :
175 : 0 : return 0;
176 : : }
177 : :
178 : : /* Returns the size of the row structure taking into account how many slices a
179 : : * TCAM supports.
180 : : */
181 : : static int
182 : : cfa_tcam_mgr_row_size_get(int sess_idx, enum tf_dir dir,
183 : : enum cfa_tcam_mgr_tbl_type type)
184 : : {
185 : 0 : return sizeof(struct cfa_tcam_mgr_table_rows_0) +
186 : 0 : (cfa_tcam_mgr_tables[sess_idx][dir][type].max_slices *
187 : : sizeof(((struct cfa_tcam_mgr_table_rows_0 *)0)->entries[0]));
188 : : }
189 : :
190 : : static void *
191 : : cfa_tcam_mgr_row_ptr_get(void *base, int index, int row_size)
192 : : {
193 : 0 : return (uint8_t *)base + (index * row_size);
194 : : }
195 : :
196 : : /*
197 : : * Searches a table to find the direction and type of an entry.
198 : : */
199 : : static int
200 : 0 : cfa_tcam_mgr_entry_find_in_table(int sess_idx, int id, enum tf_dir dir,
201 : : enum cfa_tcam_mgr_tbl_type type)
202 : : {
203 : : struct cfa_tcam_mgr_table_data *table_data;
204 : : struct cfa_tcam_mgr_table_rows_0 *row;
205 : : int max_slices, row_idx, row_size, slice;
206 : :
207 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type];
208 [ # # ]: 0 : if (table_data->max_entries > 0 &&
209 [ # # ]: 0 : table_data->hcapi_type > 0) {
210 : 0 : max_slices = table_data->max_slices;
211 : : row_size = cfa_tcam_mgr_row_size_get(sess_idx, dir, type);
212 : 0 : for (row_idx = table_data->start_row;
213 [ # # ]: 0 : row_idx <= table_data->end_row;
214 : 0 : row_idx++) {
215 : 0 : row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows,
216 : : row_idx, row_size);
217 [ # # ]: 0 : if (!ROW_INUSE(row))
218 : 0 : continue;
219 : : for (slice = 0;
220 [ # # ]: 0 : slice < (max_slices / row->entry_size);
221 : 0 : slice++) {
222 [ # # ]: 0 : if (!ROW_ENTRY_INUSE(row, slice))
223 : 0 : continue;
224 [ # # ]: 0 : if (row->entries[slice] == id)
225 : : return 0;
226 : : }
227 : : }
228 : : }
229 : :
230 : : return -CFA_TCAM_MGR_ERR_CODE(NOENT);
231 : : }
232 : :
233 : : /*
234 : : * Searches all the tables to find the direction and type of an entry.
235 : : */
236 : : static int
237 : 0 : cfa_tcam_mgr_entry_find(int sess_idx, int id, enum tf_dir *tbl_dir,
238 : : enum cfa_tcam_mgr_tbl_type *tbl_type)
239 : : {
240 : : enum tf_dir dir;
241 : : enum cfa_tcam_mgr_tbl_type type;
242 : : int rc = -CFA_TCAM_MGR_ERR_CODE(NOENT);
243 : :
244 [ # # ]: 0 : for (dir = TF_DIR_RX; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) {
245 : : for (type = CFA_TCAM_MGR_TBL_TYPE_START;
246 [ # # ]: 0 : type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]);
247 : 0 : type++) {
248 : 0 : rc = cfa_tcam_mgr_entry_find_in_table(sess_idx, id, dir, type);
249 [ # # ]: 0 : if (rc == 0) {
250 : 0 : *tbl_dir = dir;
251 : 0 : *tbl_type = type;
252 : 0 : return rc;
253 : : }
254 : : }
255 : : }
256 : :
257 : : return rc;
258 : : }
259 : :
260 : : static int
261 : : cfa_tcam_mgr_row_is_entry_free(struct cfa_tcam_mgr_table_rows_0 *row,
262 : : int max_slices,
263 : : int key_slices)
264 : : {
265 : : int j;
266 : :
267 : 0 : if (ROW_INUSE(row) &&
268 [ # # ]: 0 : row->entry_size == key_slices) {
269 [ # # ]: 0 : for (j = 0; j < (max_slices / row->entry_size); j++) {
270 [ # # ]: 0 : if (!ROW_ENTRY_INUSE(row, j))
271 : : return j;
272 : : }
273 : : }
274 : : return -1;
275 : : }
276 : :
277 : : static int
278 : 0 : cfa_tcam_mgr_entry_move(int sess_idx, struct cfa_tcam_mgr_context *context,
279 : : enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type,
280 : : int entry_id,
281 : : struct cfa_tcam_mgr_table_data *table_data,
282 : : int dest_row_index, int dest_row_slice,
283 : : struct cfa_tcam_mgr_table_rows_0 *dest_row,
284 : : int source_row_index,
285 : : struct cfa_tcam_mgr_table_rows_0 *source_row,
286 : : bool free_source_entry)
287 : : {
288 : 0 : struct cfa_tcam_mgr_get_parms gparms = { 0 };
289 : 0 : struct cfa_tcam_mgr_set_parms sparms = { 0 };
290 : 0 : struct cfa_tcam_mgr_free_parms fparms = { 0 };
291 : : struct cfa_tcam_mgr_entry_data *entry;
292 : : uint8_t key[CFA_TCAM_MGR_MAX_KEY_SIZE];
293 : : uint8_t mask[CFA_TCAM_MGR_MAX_KEY_SIZE];
294 : : uint8_t result[CFA_TCAM_MGR_MAX_KEY_SIZE];
295 : :
296 : : int j, rc;
297 : :
298 [ # # ]: 0 : entry = cfa_tcam_mgr_entry_get(sess_idx, entry_id);
299 [ # # ]: 0 : if (entry == NULL)
300 : : return -1;
301 : :
302 : 0 : gparms.dir = dir;
303 : 0 : gparms.type = type;
304 : 0 : gparms.hcapi_type = table_data->hcapi_type;
305 : 0 : gparms.key = key;
306 : 0 : gparms.mask = mask;
307 : 0 : gparms.result = result;
308 : 0 : gparms.id = source_row->entries[entry->slice];
309 : 0 : gparms.key_size = sizeof(key);
310 : 0 : gparms.result_size = sizeof(result);
311 : :
312 : 0 : rc = cfa_tcam_mgr_entry_get_msg(sess_idx, context, &gparms,
313 : : source_row_index,
314 : 0 : entry->slice * source_row->entry_size,
315 : 0 : table_data->max_slices);
316 [ # # ]: 0 : if (rc != 0)
317 : : return rc;
318 : :
319 : 0 : sparms.dir = dir;
320 : 0 : sparms.type = type;
321 : 0 : sparms.hcapi_type = table_data->hcapi_type;
322 : 0 : sparms.key = key;
323 : 0 : sparms.mask = mask;
324 : 0 : sparms.result = result;
325 : 0 : sparms.id = gparms.id;
326 : 0 : sparms.key_size = gparms.key_size;
327 : 0 : sparms.result_size = gparms.result_size;
328 : :
329 : : /* Slice in destination row not specified. Find first free slice. */
330 [ # # ]: 0 : if (dest_row_slice < 0)
331 : : for (j = 0;
332 [ # # ]: 0 : j < (table_data->max_slices / dest_row->entry_size);
333 : 0 : j++) {
334 [ # # ]: 0 : if (!ROW_ENTRY_INUSE(dest_row, j)) {
335 : : dest_row_slice = j;
336 : : break;
337 : : }
338 : : }
339 : :
340 : : /* If no free slice found, return error. */
341 [ # # ]: 0 : if (dest_row_slice < 0)
342 : : return -CFA_TCAM_MGR_ERR_CODE(PERM);
343 : :
344 : 0 : rc = cfa_tcam_mgr_entry_set_msg(sess_idx, context, &sparms,
345 : : dest_row_index,
346 : 0 : dest_row_slice * dest_row->entry_size,
347 : 0 : table_data->max_slices);
348 [ # # ]: 0 : if (rc != 0)
349 : : return rc;
350 : :
351 [ # # ]: 0 : if (free_source_entry) {
352 : 0 : fparms.dir = dir;
353 : 0 : fparms.type = type;
354 : 0 : fparms.hcapi_type = table_data->hcapi_type;
355 : 0 : rc = cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms,
356 : : source_row_index,
357 : 0 : entry->slice *
358 : 0 : dest_row->entry_size,
359 : 0 : table_data->row_width /
360 : : table_data->max_slices *
361 : 0 : source_row->entry_size,
362 : 0 : table_data->result_size,
363 : 0 : table_data->max_slices);
364 [ # # ]: 0 : if (rc != 0) {
365 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR,
366 : : dir, type,
367 : : "Failed to free entry ID %d at"
368 : : " row %d, slice %d for sess_idx %d. rc: %d.\n",
369 : : gparms.id,
370 : : source_row_index,
371 : : entry->slice,
372 : : sess_idx,
373 : : -rc);
374 : : }
375 : : }
376 : :
377 : 0 : ROW_ENTRY_SET(dest_row, dest_row_slice);
378 : 0 : dest_row->entries[dest_row_slice] = entry_id;
379 : 0 : ROW_ENTRY_CLEAR(source_row, entry->slice);
380 : 0 : entry->row = dest_row_index;
381 : 0 : entry->slice = dest_row_slice;
382 : :
383 : 0 : return 0;
384 : : }
385 : :
386 : : static int
387 : 0 : cfa_tcam_mgr_row_move(int sess_idx, struct cfa_tcam_mgr_context *context,
388 : : enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type,
389 : : struct cfa_tcam_mgr_table_data *table_data,
390 : : int dest_row_index,
391 : : struct cfa_tcam_mgr_table_rows_0 *dest_row,
392 : : int source_row_index,
393 : : struct cfa_tcam_mgr_table_rows_0 *source_row)
394 : : {
395 : 0 : struct cfa_tcam_mgr_free_parms fparms = { 0 };
396 : : int j, rc;
397 : :
398 : 0 : dest_row->priority = source_row->priority;
399 : 0 : dest_row->entry_size = source_row->entry_size;
400 : 0 : dest_row->entry_inuse = 0;
401 : :
402 : 0 : fparms.dir = dir;
403 : 0 : fparms.type = type;
404 : 0 : fparms.hcapi_type = table_data->hcapi_type;
405 : :
406 : 0 : for (j = 0;
407 [ # # ]: 0 : j < (table_data->max_slices / source_row->entry_size);
408 : 0 : j++) {
409 [ # # ]: 0 : if (ROW_ENTRY_INUSE(source_row, j)) {
410 : 0 : cfa_tcam_mgr_entry_move(sess_idx, context, dir, type,
411 : 0 : source_row->entries[j],
412 : : table_data,
413 : : dest_row_index, j, dest_row,
414 : : source_row_index, source_row,
415 : : true);
416 : : } else {
417 : : /* Slice not in use, write an empty slice. */
418 : 0 : rc = cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms,
419 : : dest_row_index,
420 : : j *
421 : : dest_row->entry_size,
422 : 0 : table_data->row_width /
423 : : table_data->max_slices *
424 : 0 : dest_row->entry_size,
425 : 0 : table_data->result_size,
426 : : table_data->max_slices);
427 [ # # ]: 0 : if (rc != 0)
428 : 0 : return rc;
429 : : }
430 : : }
431 : :
432 : : return 0;
433 : : }
434 : :
435 : : /* Install entry into in-memory tables, not into TCAM (yet). */
436 : : static void
437 : 0 : cfa_tcam_mgr_row_entry_install(int sess_idx,
438 : : struct cfa_tcam_mgr_table_rows_0 *row,
439 : : struct cfa_tcam_mgr_alloc_parms *parms,
440 : : struct cfa_tcam_mgr_entry_data *entry,
441 : : uint16_t id,
442 : : int key_slices,
443 : : int row_index, int slice)
444 : : {
445 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
446 : 0 : CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n",
447 : : sess_idx);
448 : 0 : return;
449 : : }
450 : :
451 [ # # ]: 0 : if (slice == TF_TCAM_SLICE_INVALID) {
452 : : slice = 0;
453 : 0 : row->entry_size = key_slices;
454 : 0 : row->priority = parms->priority;
455 : : }
456 : :
457 : 0 : ROW_ENTRY_SET(row, slice);
458 : 0 : row->entries[slice] = id;
459 : 0 : entry->row = row_index;
460 : 0 : entry->slice = slice;
461 : : }
462 : :
463 : : /* Finds an empty row that can be used and reserve for entry. If necessary,
464 : : * entries will be shuffled in order to make room.
465 : : */
466 : : static struct cfa_tcam_mgr_table_rows_0 *
467 : 0 : cfa_tcam_mgr_empty_row_alloc(int sess_idx, struct cfa_tcam_mgr_context *context,
468 : : struct cfa_tcam_mgr_alloc_parms *parms,
469 : : struct cfa_tcam_mgr_entry_data *entry,
470 : : uint16_t id,
471 : : int key_slices)
472 : : {
473 : : struct cfa_tcam_mgr_table_rows_0 *tcam_rows;
474 : : struct cfa_tcam_mgr_table_rows_0 *from_row;
475 : : struct cfa_tcam_mgr_table_rows_0 *to_row;
476 : : struct cfa_tcam_mgr_table_rows_0 *row;
477 : : struct cfa_tcam_mgr_table_data *table_data;
478 : : int i, max_slices, row_size;
479 : : int to_row_idx, from_row_idx, slice, start_row, end_row;
480 : : int empty_row = -1;
481 : : int target_row = -1;
482 : :
483 : 0 : table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type];
484 : :
485 : 0 : start_row = table_data->start_row;
486 : 0 : end_row = table_data->end_row;
487 : 0 : max_slices = table_data->max_slices;
488 : 0 : tcam_rows = table_data->tcam_rows;
489 : :
490 : : row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type);
491 : :
492 : : /*
493 : : * First check for partially used entries, but only if the key needs
494 : : * fewer slices than there are in a row.
495 : : */
496 [ # # ]: 0 : if (key_slices < max_slices) {
497 [ # # ]: 0 : for (i = start_row; i <= end_row; i++) {
498 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size);
499 [ # # ]: 0 : if (!ROW_INUSE(row))
500 : 0 : continue;
501 [ # # ]: 0 : if (row->priority < parms->priority)
502 : : break;
503 [ # # ]: 0 : if (row->priority > parms->priority)
504 : 0 : continue;
505 : : slice = cfa_tcam_mgr_row_is_entry_free(row,
506 : : max_slices,
507 : : key_slices);
508 [ # # ]: 0 : if (slice >= 0) {
509 : 0 : cfa_tcam_mgr_row_entry_install(sess_idx, row, parms,
510 : : entry, id,
511 : : key_slices,
512 : : i, slice);
513 : 0 : return row;
514 : : }
515 : : }
516 : : }
517 : :
518 : : /* No partially used rows available. Find an empty row, if any. */
519 : :
520 : : /*
521 : : * All max priority entries are placed in the beginning of the TCAM. It
522 : : * should not be necessary to shuffle any of these entries. All other
523 : : * priorities are placed from the end of the TCAM and may require
524 : : * shuffling.
525 : : */
526 [ # # ]: 0 : if (parms->priority == TF_TCAM_PRIORITY_MAX) {
527 : : /* Handle max priority first. */
528 [ # # ]: 0 : for (i = start_row; i <= end_row; i++) {
529 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size);
530 [ # # ]: 0 : if (!ROW_INUSE(row)) {
531 : 0 : cfa_tcam_mgr_row_entry_install(sess_idx,
532 : : row, parms,
533 : : entry,
534 : : id, key_slices,
535 : : i,
536 : : TF_TCAM_SLICE_INVALID);
537 : 0 : return row;
538 : : }
539 [ # # ]: 0 : if (row->priority < parms->priority) {
540 : : /*
541 : : * No free entries before priority change, table
542 : : * is full.
543 : : */
544 : : return NULL;
545 : : }
546 : : }
547 : : /* No free entries found, table is full. */
548 : : return NULL;
549 : : }
550 : :
551 : : /* Use the highest available entry */
552 [ # # ]: 0 : for (i = end_row; i >= start_row; i--) {
553 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size);
554 [ # # ]: 0 : if (!ROW_INUSE(row)) {
555 : : empty_row = i;
556 : : break;
557 : : }
558 : :
559 [ # # # # ]: 0 : if (row->priority > parms->priority &&
560 : : target_row < 0)
561 : : target_row = i;
562 : : }
563 : :
564 [ # # ]: 0 : if (empty_row < 0) {
565 : : /* No free entries found, table is full. */
566 : : return NULL;
567 : : }
568 : :
569 [ # # ]: 0 : if (target_row < 0) {
570 : : /*
571 : : * Did not find a row with higher priority before unused row so
572 : : * just install new entry in empty_row.
573 : : */
574 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, empty_row, row_size);
575 : 0 : cfa_tcam_mgr_row_entry_install(sess_idx, row, parms, entry, id,
576 : : key_slices, empty_row,
577 : : TF_TCAM_SLICE_INVALID);
578 : 0 : return row;
579 : : }
580 : :
581 : : to_row_idx = empty_row;
582 : : to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, to_row_idx, row_size);
583 [ # # ]: 0 : while (to_row_idx < target_row) {
584 : 0 : from_row_idx = to_row_idx + 1;
585 : : from_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, from_row_idx,
586 : : row_size);
587 : : /*
588 : : * Find the highest row with the same priority as the initial
589 : : * source row (from_row). It's only necessary to copy one row
590 : : * of each priority.
591 : : */
592 [ # # ]: 0 : for (i = from_row_idx + 1; i <= target_row; i++) {
593 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size);
594 [ # # ]: 0 : if (row->priority != from_row->priority)
595 : : break;
596 : : from_row_idx = i;
597 : : from_row = row;
598 : : }
599 : 0 : cfa_tcam_mgr_row_move(sess_idx, context, parms->dir, parms->type,
600 : : table_data, to_row_idx, to_row,
601 : : from_row_idx, from_row);
602 : : to_row = from_row;
603 : : to_row_idx = from_row_idx;
604 : : }
605 : : to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, target_row, row_size);
606 : 0 : memset(to_row, 0, row_size);
607 : 0 : cfa_tcam_mgr_row_entry_install(sess_idx, to_row, parms, entry, id,
608 : : key_slices, target_row,
609 : : TF_TCAM_SLICE_INVALID);
610 : :
611 : 0 : return row;
612 : : }
613 : :
614 : : /*
615 : : * This function will combine rows when possible to result in the fewest rows
616 : : * used necessary for the entries that are installed.
617 : : */
618 : : static void
619 : 0 : cfa_tcam_mgr_rows_combine(int sess_idx, struct cfa_tcam_mgr_context *context,
620 : : struct cfa_tcam_mgr_free_parms *parms,
621 : : struct cfa_tcam_mgr_table_data *table_data,
622 : : int changed_row_index)
623 : : {
624 : : struct cfa_tcam_mgr_table_rows_0 *from_row = NULL;
625 : : struct cfa_tcam_mgr_table_rows_0 *to_row;
626 : : struct cfa_tcam_mgr_table_rows_0 *tcam_rows;
627 : : int i, j, row_size;
628 : : int to_row_idx, from_row_idx, start_row, end_row, max_slices;
629 : : bool entry_moved = false;
630 : :
631 : 0 : start_row = table_data->start_row;
632 : 0 : end_row = table_data->end_row;
633 : 0 : max_slices = table_data->max_slices;
634 : 0 : tcam_rows = table_data->tcam_rows;
635 : :
636 : 0 : row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type);
637 : :
638 : : from_row_idx = changed_row_index;
639 : : from_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, from_row_idx, row_size);
640 : :
641 [ # # ]: 0 : if (ROW_INUSE(from_row)) {
642 : : /*
643 : : * Row is still in partial use. See if remaining entry(s) can
644 : : * be moved to free up a row.
645 : : */
646 [ # # ]: 0 : for (i = 0; i < (max_slices / from_row->entry_size); i++) {
647 [ # # ]: 0 : if (!ROW_ENTRY_INUSE(from_row, i))
648 : 0 : continue;
649 : : for (to_row_idx = end_row;
650 [ # # ]: 0 : to_row_idx >= start_row;
651 : 0 : to_row_idx--) {
652 : : to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows,
653 : : to_row_idx,
654 : : row_size);
655 [ # # ]: 0 : if (!ROW_INUSE(to_row))
656 : 0 : continue;
657 [ # # ]: 0 : if (to_row->priority > from_row->priority)
658 : : break;
659 [ # # ]: 0 : if (to_row->priority != from_row->priority)
660 : 0 : continue;
661 [ # # ]: 0 : if (to_row->entry_size != from_row->entry_size)
662 : 0 : continue;
663 [ # # ]: 0 : if (to_row_idx == changed_row_index)
664 : 0 : continue;
665 : : for (j = 0;
666 [ # # ]: 0 : j < (max_slices / to_row->entry_size);
667 : 0 : j++) {
668 [ # # ]: 0 : if (!ROW_ENTRY_INUSE(to_row, j)) {
669 : 0 : cfa_tcam_mgr_entry_move
670 : : (sess_idx,
671 : : context,
672 : : parms->dir,
673 : : parms->type,
674 : 0 : from_row->entries[i],
675 : : table_data,
676 : : to_row_idx,
677 : : -1, to_row,
678 : : from_row_idx,
679 : : from_row,
680 : : true);
681 : : entry_moved = true;
682 : : break;
683 : : }
684 : : }
685 : : if (entry_moved)
686 : : break;
687 : : }
688 [ # # ]: 0 : if (ROW_INUSE(from_row))
689 : : entry_moved = false;
690 : : else
691 : : break;
692 : : }
693 : : }
694 : 0 : }
695 : :
696 : : /*
697 : : * This function will ensure that all rows, except those of the highest
698 : : * priority, at the end of the table. When this function is finished, all the
699 : : * empty rows should be between the highest priority rows at the beginning of
700 : : * the table and the rest of the rows with lower priorities.
701 : : */
702 : : /*
703 : : * Will need to free the row left newly empty as a result of moving.
704 : : *
705 : : * Return row to free to caller. If new_row_to_free < 0, then no new row to
706 : : * free.
707 : : */
708 : : static void
709 : 0 : cfa_tcam_mgr_rows_compact(int sess_idx, struct cfa_tcam_mgr_context *context,
710 : : struct cfa_tcam_mgr_free_parms *parms,
711 : : struct cfa_tcam_mgr_table_data *table_data,
712 : : int *new_row_to_free,
713 : : int changed_row_index)
714 : : {
715 : : struct cfa_tcam_mgr_table_rows_0 *from_row = NULL;
716 : : struct cfa_tcam_mgr_table_rows_0 *to_row;
717 : : struct cfa_tcam_mgr_table_rows_0 *row;
718 : : struct cfa_tcam_mgr_table_rows_0 *tcam_rows;
719 : : int i, row_size, priority;
720 : : int to_row_idx = 0, from_row_idx = 0, start_row = 0, end_row = 0;
721 : :
722 : 0 : *new_row_to_free = -1;
723 : :
724 : 0 : start_row = table_data->start_row;
725 : 0 : end_row = table_data->end_row;
726 : 0 : tcam_rows = table_data->tcam_rows;
727 : :
728 : 0 : row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type);
729 : :
730 : : /*
731 : : * The row is no longer in use, so see if rows need to be moved in order
732 : : * to not leave any gaps.
733 : : */
734 : : to_row_idx = changed_row_index;
735 : : to_row = cfa_tcam_mgr_row_ptr_get(tcam_rows, to_row_idx, row_size);
736 : :
737 : 0 : priority = to_row->priority;
738 [ # # ]: 0 : if (priority == TF_TCAM_PRIORITY_MAX) {
739 [ # # ]: 0 : if (changed_row_index == end_row)
740 : : /*
741 : : * Nothing to move - the last row in the TCAM is being
742 : : * deleted.
743 : : */
744 : : return;
745 [ # # ]: 0 : for (i = changed_row_index + 1; i <= end_row; i++) {
746 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size);
747 [ # # ]: 0 : if (!ROW_INUSE(row))
748 : : break;
749 : :
750 [ # # ]: 0 : if (row->priority < priority)
751 : : break;
752 : :
753 : : from_row = row;
754 : : from_row_idx = i;
755 : : }
756 : : } else {
757 [ # # ]: 0 : if (changed_row_index == start_row)
758 : : /*
759 : : * Nothing to move - the first row in the TCAM is being
760 : : * deleted.
761 : : */
762 : : return;
763 [ # # ]: 0 : for (i = changed_row_index - 1; i >= start_row; i--) {
764 : : row = cfa_tcam_mgr_row_ptr_get(tcam_rows, i, row_size);
765 [ # # ]: 0 : if (!ROW_INUSE(row))
766 : : break;
767 : :
768 [ # # ]: 0 : if (row->priority > priority) {
769 : : /* Don't move the highest priority rows. */
770 [ # # ]: 0 : if (row->priority == TF_TCAM_PRIORITY_MAX)
771 : : break;
772 : : /*
773 : : * If from_row is NULL, that means that there
774 : : * were no rows of the deleted priority.
775 : : * Nothing to move yet.
776 : : *
777 : : * If from_row is not NULL, then it is the last
778 : : * row with the same priority and must be moved
779 : : * to fill the newly empty (by free or by move)
780 : : * row.
781 : : */
782 [ # # ]: 0 : if (from_row != NULL) {
783 : 0 : cfa_tcam_mgr_row_move(sess_idx, context,
784 : : parms->dir,
785 : : parms->type,
786 : : table_data,
787 : : to_row_idx, to_row,
788 : : from_row_idx,
789 : : from_row);
790 : 0 : *new_row_to_free = from_row_idx;
791 : : to_row = from_row;
792 : : to_row_idx = from_row_idx;
793 : : }
794 : :
795 : 0 : priority = row->priority;
796 : : }
797 : : from_row = row;
798 : : from_row_idx = i;
799 : : }
800 : : }
801 : :
802 [ # # ]: 0 : if (from_row != NULL) {
803 : 0 : cfa_tcam_mgr_row_move(sess_idx, context, parms->dir, parms->type,
804 : : table_data,
805 : : to_row_idx, to_row,
806 : : from_row_idx, from_row);
807 : 0 : *new_row_to_free = from_row_idx;
808 : : }
809 : : }
810 : :
811 : : /*
812 : : * This function is to set table limits for the logical TCAM tables.
813 : : */
814 : : static int
815 : 0 : cfa_tcam_mgr_table_limits_set(int sess_idx, struct cfa_tcam_mgr_init_parms *parms)
816 : : {
817 : : struct cfa_tcam_mgr_table_data *table_data;
818 : : unsigned int dir, type;
819 : : int start, stride;
820 : :
821 [ # # ]: 0 : if (parms == NULL)
822 : : return 0;
823 : :
824 [ # # ]: 0 : for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++)
825 : : for (type = 0;
826 [ # # ]: 0 : type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]);
827 : 0 : type++) {
828 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type];
829 : : /*
830 : : * If num_rows is zero, then TCAM Manager did not
831 : : * allocate any row storage for that table so cannot
832 : : * manage it.
833 : : */
834 [ # # ]: 0 : if (table_data->num_rows == 0)
835 : 0 : continue;
836 : 0 : start = parms->resc[dir][type].start;
837 : 0 : stride = parms->resc[dir][type].stride;
838 [ # # ]: 0 : if (start % table_data->max_slices > 0) {
839 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type,
840 : : "Start of resources (%d) for table (%d) "
841 : : "does not begin on row boundary.\n",
842 : : start, sess_idx);
843 : 0 : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
844 : : "Start is %d, number of slices "
845 : : "is %d.\n",
846 : : start,
847 : : table_data->max_slices);
848 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
849 : : }
850 [ # # ]: 0 : if (stride % table_data->max_slices > 0) {
851 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type,
852 : : "Stride of resources (%d) for table (%d)"
853 : : " does not end on row boundary.\n",
854 : : stride, sess_idx);
855 : 0 : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
856 : : "Stride is %d, number of "
857 : : "slices is %d.\n",
858 : : stride,
859 : : table_data->max_slices);
860 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
861 : : }
862 [ # # ]: 0 : if (stride == 0) {
863 : 0 : table_data->start_row = 0;
864 : 0 : table_data->end_row = 0;
865 : 0 : table_data->max_entries = 0;
866 : : } else {
867 : 0 : table_data->start_row = start /
868 : : table_data->max_slices;
869 : 0 : table_data->end_row = table_data->start_row +
870 : 0 : (stride / table_data->max_slices) - 1;
871 : 0 : table_data->max_entries =
872 : : table_data->max_slices *
873 : 0 : (table_data->end_row -
874 : 0 : table_data->start_row + 1);
875 : : }
876 : : }
877 : :
878 : : return 0;
879 : : }
880 : :
881 : : int
882 : 0 : cfa_tcam_mgr_init(int sess_idx, enum cfa_tcam_mgr_device_type type,
883 : : struct cfa_tcam_mgr_init_parms *parms)
884 : : {
885 : : struct cfa_tcam_mgr_table_data *table_data;
886 : : unsigned int dir, tbl_type;
887 : : int rc;
888 : :
889 [ # # # ]: 0 : switch (type) {
890 : 0 : case CFA_TCAM_MGR_DEVICE_TYPE_P4:
891 : : case CFA_TCAM_MGR_DEVICE_TYPE_SR:
892 : 0 : rc = cfa_tcam_mgr_init_p4(sess_idx, &entry_data[sess_idx]);
893 : 0 : break;
894 : 0 : case CFA_TCAM_MGR_DEVICE_TYPE_P5:
895 : 0 : rc = cfa_tcam_mgr_init_p58(sess_idx, &entry_data[sess_idx]);
896 : 0 : break;
897 : 0 : default:
898 : 0 : CFA_TCAM_MGR_LOG(ERR, "No such device %d for sess_idx %d\n",
899 : : type, sess_idx);
900 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NODEV);
901 : : }
902 [ # # ]: 0 : if (rc < 0)
903 : : return rc;
904 : :
905 : 0 : rc = cfa_tcam_mgr_table_limits_set(sess_idx, parms);
906 [ # # ]: 0 : if (rc < 0)
907 : : return rc;
908 : :
909 : : /* Now calculate the max entries per table and global max entries based
910 : : * on the updated table limits.
911 : : */
912 [ # # ]: 0 : for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++)
913 : : for (tbl_type = 0;
914 [ # # ]: 0 : tbl_type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]);
915 : 0 : tbl_type++) {
916 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][tbl_type];
917 : : /*
918 : : * If num_rows is zero, then TCAM Manager did not
919 : : * allocate any row storage for that table so cannot
920 : : * manage it.
921 : : */
922 [ # # ]: 0 : if (table_data->num_rows == 0) {
923 : 0 : table_data->start_row = 0;
924 : 0 : table_data->end_row = 0;
925 : 0 : table_data->max_entries = 0;
926 [ # # ]: 0 : } else if (table_data->end_row >=
927 : : table_data->num_rows) {
928 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(EMERG, dir, tbl_type,
929 : : "End row is out of "
930 : : "range (%d >= %d) for sess_idx %d\n",
931 : : table_data->end_row,
932 : : table_data->num_rows,
933 : : sess_idx);
934 : 0 : return -CFA_TCAM_MGR_ERR_CODE(FAULT);
935 [ # # ]: 0 : } else if (table_data->max_entries == 0 &&
936 [ # # ]: 0 : table_data->start_row == 0 &&
937 : : table_data->end_row == 0) {
938 : : /* Nothing to do */
939 : : } else {
940 : 0 : table_data->max_entries =
941 : 0 : table_data->max_slices *
942 : 0 : (table_data->end_row -
943 : 0 : table_data->start_row + 1);
944 : : }
945 : 0 : cfa_tcam_mgr_max_entries[sess_idx] += table_data->max_entries;
946 : : }
947 : :
948 : 0 : rc = cfa_tcam_mgr_hwops_init(type);
949 [ # # ]: 0 : if (rc < 0)
950 : : return rc;
951 : :
952 : 0 : rc = cfa_tcam_mgr_session_init(sess_idx, type);
953 [ # # ]: 0 : if (rc < 0)
954 : : return rc;
955 : :
956 : 0 : global_data_initialized[sess_idx] = 1;
957 : :
958 [ # # ]: 0 : if (parms != NULL)
959 : 0 : parms->max_entries = cfa_tcam_mgr_max_entries[sess_idx];
960 : :
961 : 0 : CFA_TCAM_MGR_LOG(INFO, "Global TCAM table initialized for sess_idx %d.\n",
962 : : sess_idx);
963 : :
964 : 0 : return 0;
965 : : }
966 : :
967 : : int
968 : 0 : cfa_tcam_mgr_qcaps(struct cfa_tcam_mgr_context *context __rte_unused,
969 : : struct cfa_tcam_mgr_qcaps_parms *parms)
970 : : {
971 : : unsigned int type;
972 : : int rc, sess_idx;
973 : : uint32_t session_id;
974 : :
975 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
976 : :
977 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
978 [ # # ]: 0 : if (rc < 0)
979 : : return rc;
980 : :
981 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
982 [ # # ]: 0 : if (sess_idx < 0) {
983 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n");
984 : 0 : return sess_idx;
985 : : }
986 : :
987 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
988 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n",
989 : : sess_idx);
990 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
991 : : }
992 : :
993 : : /*
994 : : * This code will indicate if TCAM Manager is managing a logical TCAM
995 : : * table or not. If not, then the physical TCAM will have to be
996 : : * accessed using the traditional methods.
997 : : */
998 : 0 : parms->rx_tcam_supported = 0;
999 : 0 : parms->tx_tcam_supported = 0;
1000 [ # # ]: 0 : for (type = 0; type < CFA_TCAM_MGR_TBL_TYPE_MAX; type++) {
1001 [ # # ]: 0 : if (cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX][type].max_entries > 0 &&
1002 [ # # ]: 0 : cfa_tcam_mgr_tables[sess_idx][TF_DIR_RX][type].hcapi_type > 0)
1003 : 0 : parms->rx_tcam_supported |= 1 << cfa_tcam_mgr_get_phys_table_type(type);
1004 [ # # ]: 0 : if (cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX][type].max_entries > 0 &&
1005 [ # # ]: 0 : cfa_tcam_mgr_tables[sess_idx][TF_DIR_TX][type].hcapi_type > 0)
1006 : 0 : parms->tx_tcam_supported |= 1 << cfa_tcam_mgr_get_phys_table_type(type);
1007 : : }
1008 : :
1009 : : return 0;
1010 : : }
1011 : :
1012 : : /*
1013 : : * Manipulate the tables to split the WC TCAM into HIGH and LOW ranges
1014 : : * and also update the sizes in the tcam count array
1015 : : */
1016 : : static int
1017 : 0 : cfa_tcam_mgr_shared_wc_bind(uint32_t sess_idx, bool dual_ha_app,
1018 : : uint16_t tcam_cnt[][CFA_TCAM_MGR_TBL_TYPE_MAX])
1019 : : {
1020 : : uint16_t start_row, end_row, max_entries, slices;
1021 [ # # ]: 0 : uint16_t num_pools = dual_ha_app ? 4 : 2;
1022 : : enum tf_dir dir;
1023 : : int rc;
1024 : :
1025 [ # # ]: 0 : for (dir = 0; dir < TF_DIR_MAX; dir++) {
1026 : 0 : rc = cfa_tcam_mgr_tables_get(sess_idx, dir,
1027 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS,
1028 : : &start_row, &end_row, &max_entries, &slices);
1029 [ # # ]: 0 : if (rc)
1030 : 0 : return rc;
1031 [ # # ]: 0 : if (max_entries) {
1032 : 0 : rc = cfa_tcam_mgr_tables_set(sess_idx, dir,
1033 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS,
1034 : : start_row,
1035 : 0 : start_row +
1036 : 0 : ((max_entries / slices) / num_pools) - 1,
1037 : : max_entries / num_pools);
1038 [ # # ]: 0 : if (rc)
1039 : 0 : return rc;
1040 : 0 : rc = cfa_tcam_mgr_tables_set(sess_idx, dir,
1041 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS,
1042 : 0 : start_row +
1043 : 0 : ((max_entries / slices) / num_pools),
1044 : 0 : start_row +
1045 : 0 : (max_entries / slices) - 1,
1046 : : max_entries / num_pools);
1047 [ # # ]: 0 : if (rc)
1048 : 0 : return rc;
1049 : 0 : rc = cfa_tcam_mgr_tables_set(sess_idx, dir,
1050 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS,
1051 : : 0, 0, 0);
1052 [ # # ]: 0 : if (rc)
1053 : 0 : return rc;
1054 : 0 : tcam_cnt[dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS] =
1055 : : max_entries / num_pools;
1056 : 0 : tcam_cnt[dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS] =
1057 : : max_entries / num_pools;
1058 : 0 : tcam_cnt[dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_APPS] = 0;
1059 : : }
1060 : : }
1061 : :
1062 : : return 0;
1063 : : }
1064 : :
1065 : : int
1066 : 0 : cfa_tcam_mgr_bind(struct cfa_tcam_mgr_context *context,
1067 : : struct cfa_tcam_mgr_cfg_parms *parms)
1068 : : {
1069 : : struct cfa_tcam_mgr_table_data *table_data;
1070 : : struct tf_dev_info *dev;
1071 : : unsigned int dir;
1072 : : int rc, sess_idx;
1073 : : uint32_t session_id;
1074 : : struct tf_session *tfs;
1075 : : unsigned int type;
1076 : : int prev_max_entries;
1077 : : int start, stride;
1078 : : enum cfa_tcam_mgr_device_type device_type;
1079 : :
1080 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1081 : :
1082 : : /* Retrieve the session information */
1083 : 0 : rc = tf_session_get_session_internal(context->tfp, &tfs);
1084 [ # # ]: 0 : if (rc)
1085 : : return rc;
1086 : :
1087 : : /* Retrieve the device information */
1088 : 0 : rc = tf_session_get_device(tfs, &dev);
1089 [ # # ]: 0 : if (rc)
1090 : : return rc;
1091 : :
1092 [ # # ]: 0 : switch (dev->type) {
1093 : : case TF_DEVICE_TYPE_P4:
1094 : : device_type = CFA_TCAM_MGR_DEVICE_TYPE_P4;
1095 : : break;
1096 : : case TF_DEVICE_TYPE_SR:
1097 : : device_type = CFA_TCAM_MGR_DEVICE_TYPE_SR;
1098 : : break;
1099 : : case TF_DEVICE_TYPE_P5:
1100 : : device_type = CFA_TCAM_MGR_DEVICE_TYPE_P5;
1101 : : break;
1102 : 0 : default:
1103 : 0 : CFA_TCAM_MGR_LOG(ERR, "No such device %d\n", dev->type);
1104 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NODEV);
1105 : : }
1106 : :
1107 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1108 [ # # ]: 0 : if (rc < 0)
1109 : : return rc;
1110 : :
1111 : 0 : sess_idx = cfa_tcam_mgr_session_add(session_id);
1112 [ # # ]: 0 : if (sess_idx < 0)
1113 : : return sess_idx;
1114 : :
1115 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1116 : 0 : rc = cfa_tcam_mgr_init(sess_idx, device_type, NULL);
1117 [ # # ]: 0 : if (rc < 0)
1118 : : return rc;
1119 : : }
1120 : :
1121 [ # # ]: 0 : if (parms->num_elements != ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir])) {
1122 : 0 : CFA_TCAM_MGR_LOG(ERR,
1123 : : "Session element count (%d) differs "
1124 : : "from table count (%zu) for sess_idx %d.\n",
1125 : : parms->num_elements,
1126 : : ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]),
1127 : : sess_idx);
1128 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1129 : : }
1130 : :
1131 : : /*
1132 : : * Only managing one session. resv_res contains the resources allocated
1133 : : * to this session by the resource manager. Update the limits on TCAMs.
1134 : : */
1135 [ # # ]: 0 : for (dir = 0; dir < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx]); dir++) {
1136 : : for (type = 0;
1137 [ # # ]: 0 : type < ARRAY_SIZE(cfa_tcam_mgr_tables[sess_idx][dir]);
1138 : 0 : type++) {
1139 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type];
1140 : 0 : prev_max_entries = table_data->max_entries;
1141 : : /*
1142 : : * In AFM logical tables, max_entries is initialized to
1143 : : * zero. These logical tables are not used when TCAM
1144 : : * Manager is in the core so skip.
1145 : : */
1146 [ # # ]: 0 : if (prev_max_entries == 0)
1147 : 0 : continue;
1148 : 0 : start = parms->resv_res[dir][type].start;
1149 : 0 : stride = parms->resv_res[dir][type].stride;
1150 [ # # ]: 0 : if (start % table_data->max_slices > 0) {
1151 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type,
1152 : : "Start of resources (%d) for table(%d) "
1153 : : "does not begin on row boundary.\n",
1154 : : start, sess_idx);
1155 : 0 : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
1156 : : "Start is %d, number of slices "
1157 : : "is %d.\n",
1158 : : start,
1159 : : table_data->max_slices);
1160 : 0 : (void)cfa_tcam_mgr_session_free(session_id, context);
1161 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1162 : : }
1163 [ # # ]: 0 : if (stride % table_data->max_slices > 0) {
1164 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, type,
1165 : : "Stride of resources (%d) for table(%d) "
1166 : : "does not end on row boundary.\n",
1167 : : stride, sess_idx);
1168 : 0 : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
1169 : : "Stride is %d, number of "
1170 : : "slices is %d.\n",
1171 : : stride,
1172 : : table_data->max_slices);
1173 : 0 : (void)cfa_tcam_mgr_session_free(session_id, context);
1174 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1175 : : }
1176 [ # # ]: 0 : if (stride == 0) {
1177 : 0 : table_data->start_row = 0;
1178 : 0 : table_data->end_row = 0;
1179 : 0 : table_data->max_entries = 0;
1180 : : } else {
1181 : 0 : table_data->start_row = start /
1182 : : table_data->max_slices;
1183 : 0 : table_data->end_row = table_data->start_row +
1184 : 0 : (stride / table_data->max_slices) - 1;
1185 : 0 : table_data->max_entries =
1186 : : table_data->max_slices *
1187 : 0 : (table_data->end_row -
1188 : 0 : table_data->start_row + 1);
1189 : : }
1190 : 0 : cfa_tcam_mgr_max_entries[sess_idx] += (table_data->max_entries -
1191 : : prev_max_entries);
1192 : : }
1193 : : }
1194 : :
1195 [ # # ]: 0 : if (tf_session_is_shared_hotup_session(tfs)) {
1196 : 0 : rc = cfa_tcam_mgr_shared_wc_bind(sess_idx, false, parms->tcam_cnt);
1197 [ # # ]: 0 : if (rc) {
1198 : 0 : (void)cfa_tcam_mgr_session_free(session_id, context);
1199 : 0 : return rc;
1200 : : }
1201 : : }
1202 : :
1203 : 0 : rc = cfa_tcam_mgr_session_cfg(session_id, parms->tcam_cnt);
1204 [ # # ]: 0 : if (rc < 0) {
1205 : 0 : (void)cfa_tcam_mgr_session_free(session_id, context);
1206 : 0 : return rc;
1207 : : }
1208 : :
1209 : : return 0;
1210 : : }
1211 : :
1212 : : int
1213 : 0 : cfa_tcam_mgr_unbind(struct cfa_tcam_mgr_context *context)
1214 : : {
1215 : : int rc, sess_idx;
1216 : : uint32_t session_id;
1217 : :
1218 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS1(context);
1219 : :
1220 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1221 [ # # ]: 0 : if (rc < 0)
1222 : : return rc;
1223 : :
1224 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1225 [ # # ]: 0 : if (sess_idx < 0) {
1226 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Session not found.\n");
1227 : 0 : return sess_idx;
1228 : : }
1229 : :
1230 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1231 : 0 : CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n",
1232 : : sess_idx);
1233 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1234 : : }
1235 : :
1236 : 0 : (void)cfa_tcam_mgr_session_free(session_id, context);
1237 : :
1238 : 0 : global_data_initialized[sess_idx] = 0;
1239 : 0 : return 0;
1240 : : }
1241 : :
1242 : : int
1243 : 0 : cfa_tcam_mgr_alloc(struct cfa_tcam_mgr_context *context,
1244 : : struct cfa_tcam_mgr_alloc_parms *parms)
1245 : : {
1246 : : struct cfa_tcam_mgr_entry_data entry;
1247 : : struct cfa_tcam_mgr_table_rows_0 *row;
1248 : : struct cfa_tcam_mgr_table_data *table_data;
1249 : : int dir, tbl_type;
1250 : : int key_slices, rc, sess_idx;
1251 : : int new_entry_id;
1252 : : uint32_t session_id;
1253 : :
1254 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1255 : :
1256 : 0 : dir = parms->dir;
1257 : 0 : tbl_type = parms->type;
1258 : :
1259 [ # # ]: 0 : if (dir >= TF_DIR_MAX) {
1260 : 0 : CFA_TCAM_MGR_LOG(ERR, "Invalid direction: %d.\n", dir);
1261 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1262 : : }
1263 : :
1264 [ # # ]: 0 : if (tbl_type >= CFA_TCAM_MGR_TBL_TYPE_MAX) {
1265 : 0 : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
1266 : : "Invalid table type: %d.\n",
1267 : : tbl_type);
1268 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1269 : : }
1270 : :
1271 : : #if TF_TCAM_PRIORITY_MAX < UINT16_MAX
1272 : : if (parms->priority > TF_TCAM_PRIORITY_MAX) {
1273 : : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
1274 : : "Priority (%u) out of range (%u -%u).\n",
1275 : : parms->priority,
1276 : : TF_TCAM_PRIORITY_MIN,
1277 : : TF_TCAM_PRIORITY_MAX);
1278 : : }
1279 : : #endif
1280 : :
1281 : : /* Check for session limits */
1282 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1283 [ # # ]: 0 : if (rc < 0)
1284 : : return rc;
1285 : :
1286 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1287 [ # # ]: 0 : if (sess_idx < 0) {
1288 : 0 : CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n",
1289 : : session_id);
1290 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NODEV);
1291 : : }
1292 : :
1293 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1294 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n",
1295 : : sess_idx);
1296 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1297 : : }
1298 : :
1299 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][tbl_type];
1300 : :
1301 [ # # ]: 0 : if (parms->key_size == 0 ||
1302 [ # # ]: 0 : parms->key_size > table_data->row_width) {
1303 : 0 : CFA_TCAM_MGR_LOG_DIR(ERR, dir,
1304 : : "Invalid key size:%d (range 1-%d) sess_idx %d.\n",
1305 : : parms->key_size,
1306 : : table_data->row_width,
1307 : : sess_idx);
1308 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1309 : : }
1310 : :
1311 : : /* Check global limits */
1312 : 0 : if (table_data->used_entries >=
1313 [ # # ]: 0 : table_data->max_entries) {
1314 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, dir, tbl_type,
1315 : : "Table full sess_idx %d.\n",
1316 : : sess_idx);
1317 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NOSPC);
1318 : : }
1319 : :
1320 : : /* There is room, now increment counts and allocate an entry. */
1321 : 0 : new_entry_id = cfa_tcam_mgr_session_entry_alloc(session_id,
1322 : : parms->dir,
1323 : : parms->type);
1324 [ # # ]: 0 : if (new_entry_id < 0)
1325 : : return new_entry_id;
1326 : :
1327 : : memset(&entry, 0, sizeof(entry));
1328 : 0 : entry.ref_cnt++;
1329 : :
1330 : 0 : key_slices = cfa_tcam_mgr_get_num_slices(parms->key_size,
1331 : 0 : (table_data->row_width /
1332 [ # # ]: 0 : table_data->max_slices));
1333 : :
1334 : 0 : row = cfa_tcam_mgr_empty_row_alloc(sess_idx, context, parms, &entry,
1335 : : new_entry_id, key_slices);
1336 [ # # ]: 0 : if (row == NULL) {
1337 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR, parms->dir, parms->type,
1338 : : "Table full (HW) sess_idx %d.\n",
1339 : : sess_idx);
1340 : 0 : (void)cfa_tcam_mgr_session_entry_free(session_id, new_entry_id,
1341 : : parms->dir, parms->type);
1342 : 0 : return -CFA_TCAM_MGR_ERR_CODE(NOSPC);
1343 : : }
1344 : :
1345 : 0 : memcpy(&entry_data[sess_idx][new_entry_id],
1346 : : &entry,
1347 : : sizeof(entry_data[sess_idx][new_entry_id]));
1348 : 0 : table_data->used_entries += 1;
1349 : :
1350 : 0 : cfa_tcam_mgr_entry_insert(sess_idx, new_entry_id, &entry);
1351 : :
1352 : 0 : parms->id = new_entry_id;
1353 : :
1354 : 0 : return 0;
1355 : : }
1356 : :
1357 : : int
1358 : 0 : cfa_tcam_mgr_free(struct cfa_tcam_mgr_context *context,
1359 : : struct cfa_tcam_mgr_free_parms *parms)
1360 : : {
1361 : : struct cfa_tcam_mgr_entry_data *entry;
1362 : : struct cfa_tcam_mgr_table_rows_0 *row;
1363 : : struct cfa_tcam_mgr_table_data *table_data;
1364 : : int row_size, rc, sess_idx, new_row_to_free;
1365 : : uint32_t session_id;
1366 : : uint16_t id;
1367 : :
1368 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1369 : :
1370 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1371 [ # # ]: 0 : if (rc < 0)
1372 : : return rc;
1373 : :
1374 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1375 [ # # ]: 0 : if (sess_idx < 0) {
1376 : 0 : CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n",
1377 : : session_id);
1378 : 0 : return sess_idx;
1379 : : }
1380 : :
1381 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1382 : 0 : CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n",
1383 : : sess_idx);
1384 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1385 : : }
1386 : :
1387 : 0 : id = parms->id;
1388 [ # # ]: 0 : entry = cfa_tcam_mgr_entry_get(sess_idx, id);
1389 [ # # ]: 0 : if (entry == NULL) {
1390 : 0 : CFA_TCAM_MGR_LOG(INFO, "Entry %d not found for sess_idx %d.\n",
1391 : : id, sess_idx);
1392 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1393 : : }
1394 : :
1395 [ # # ]: 0 : if (entry->ref_cnt == 0) {
1396 : 0 : CFA_TCAM_MGR_LOG(ERR, "Entry %d not in use for sess_idx %d.\n",
1397 : : id, sess_idx);
1398 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1399 : : }
1400 : :
1401 : : /*
1402 : : * If the TCAM type is CFA_TCAM_MGR_TBL_TYPE_MAX, that implies that the
1403 : : * caller does not know the table or direction of the entry and TCAM
1404 : : * Manager must search the tables to find out which table has the entry
1405 : : * installed.
1406 : : *
1407 : : * This would be the case if RM has informed TCAM Mgr that an entry must
1408 : : * be freed. Clients (sessions, AFM) should always know the type and
1409 : : * direction of the table where an entry is installed.
1410 : : */
1411 [ # # ]: 0 : if (parms->type == CFA_TCAM_MGR_TBL_TYPE_MAX) {
1412 : : /* Need to search for the entry in the tables */
1413 : 0 : rc = cfa_tcam_mgr_entry_find(sess_idx, id, &parms->dir, &parms->type);
1414 [ # # ]: 0 : if (rc < 0) {
1415 : 0 : CFA_TCAM_MGR_LOG(ERR, "Entry %d not in tables for sess_idx %d.\n",
1416 : : id, sess_idx);
1417 : 0 : return rc;
1418 : : }
1419 : : }
1420 : :
1421 : 0 : table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type];
1422 : 0 : parms->hcapi_type = table_data->hcapi_type;
1423 : :
1424 : : row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type);
1425 : :
1426 : 0 : row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, entry->row,
1427 : : row_size);
1428 : :
1429 : 0 : entry->ref_cnt--;
1430 : :
1431 : 0 : (void)cfa_tcam_mgr_session_entry_free(session_id, id,
1432 : : parms->dir, parms->type);
1433 : :
1434 [ # # ]: 0 : if (entry->ref_cnt == 0) {
1435 : 0 : cfa_tcam_mgr_entry_free_msg(sess_idx, context, parms,
1436 : 0 : entry->row,
1437 : 0 : entry->slice * row->entry_size,
1438 : 0 : table_data->row_width /
1439 : : table_data->max_slices *
1440 : 0 : row->entry_size,
1441 : 0 : table_data->result_size,
1442 : 0 : table_data->max_slices);
1443 : 0 : ROW_ENTRY_CLEAR(row, entry->slice);
1444 : :
1445 : 0 : new_row_to_free = entry->row;
1446 : 0 : cfa_tcam_mgr_rows_combine(sess_idx, context, parms, table_data,
1447 : : new_row_to_free);
1448 : :
1449 [ # # ]: 0 : if (!ROW_INUSE(row)) {
1450 : 0 : cfa_tcam_mgr_rows_compact(sess_idx, context,
1451 : : parms, table_data,
1452 : : &new_row_to_free,
1453 : : new_row_to_free);
1454 [ # # ]: 0 : if (new_row_to_free >= 0)
1455 : 0 : cfa_tcam_mgr_entry_free_msg(sess_idx, context, parms,
1456 : : new_row_to_free, 0,
1457 : 0 : table_data->row_width,
1458 : 0 : table_data->result_size,
1459 : 0 : table_data->max_slices);
1460 : : }
1461 : :
1462 : 0 : cfa_tcam_mgr_entry_delete(sess_idx, id);
1463 : 0 : table_data->used_entries -= 1;
1464 : : }
1465 : :
1466 : : return 0;
1467 : : }
1468 : :
1469 : : int
1470 : 0 : cfa_tcam_mgr_set(struct cfa_tcam_mgr_context *context,
1471 : : struct cfa_tcam_mgr_set_parms *parms)
1472 : : {
1473 : : struct cfa_tcam_mgr_entry_data *entry;
1474 : : struct cfa_tcam_mgr_table_rows_0 *row;
1475 : : struct cfa_tcam_mgr_table_data *table_data;
1476 : : int rc;
1477 : : int row_size, sess_idx;
1478 : : int entry_size_in_bytes;
1479 : : uint32_t session_id;
1480 : :
1481 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1482 : :
1483 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1484 [ # # ]: 0 : if (rc < 0)
1485 : : return rc;
1486 : :
1487 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1488 [ # # ]: 0 : if (sess_idx < 0) {
1489 : 0 : CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n",
1490 : : session_id);
1491 : 0 : return sess_idx;
1492 : : }
1493 : :
1494 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1495 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n",
1496 : : sess_idx);
1497 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1498 : : }
1499 : :
1500 [ # # ]: 0 : entry = cfa_tcam_mgr_entry_get(sess_idx, parms->id);
1501 [ # # ]: 0 : if (entry == NULL) {
1502 : 0 : CFA_TCAM_MGR_LOG(ERR, "Entry %d not found for sess_idx %d.\n",
1503 : : parms->id, sess_idx);
1504 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1505 : : }
1506 : :
1507 : 0 : table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type];
1508 : 0 : parms->hcapi_type = table_data->hcapi_type;
1509 : :
1510 : : row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type);
1511 : 0 : row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, entry->row,
1512 : : row_size);
1513 : :
1514 : 0 : entry_size_in_bytes = table_data->row_width /
1515 : : table_data->max_slices *
1516 : 0 : row->entry_size;
1517 [ # # ]: 0 : if (parms->key_size != entry_size_in_bytes) {
1518 : 0 : CFA_TCAM_MGR_LOG(ERR,
1519 : : "Key size(%d) is different from entry "
1520 : : "size(%d).\n",
1521 : : parms->key_size,
1522 : : entry_size_in_bytes);
1523 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1524 : : }
1525 : :
1526 : 0 : rc = cfa_tcam_mgr_entry_set_msg(sess_idx, context, parms,
1527 : : entry->row,
1528 : 0 : entry->slice * row->entry_size,
1529 : : table_data->max_slices);
1530 [ # # ]: 0 : if (rc < 0) {
1531 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Failed to set TCAM data.\n");
1532 : 0 : return rc;
1533 : : }
1534 : :
1535 : : return 0;
1536 : : }
1537 : :
1538 : : int
1539 : 0 : cfa_tcam_mgr_get(struct cfa_tcam_mgr_context *context __rte_unused,
1540 : : struct cfa_tcam_mgr_get_parms *parms)
1541 : : {
1542 : : struct cfa_tcam_mgr_entry_data *entry;
1543 : : struct cfa_tcam_mgr_table_rows_0 *row;
1544 : : struct cfa_tcam_mgr_table_data *table_data;
1545 : : int rc;
1546 : : int row_size, sess_idx;
1547 : : uint32_t session_id;
1548 : :
1549 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1550 : :
1551 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1552 [ # # ]: 0 : if (rc < 0)
1553 : : return rc;
1554 : :
1555 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1556 [ # # ]: 0 : if (sess_idx < 0) {
1557 : 0 : CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n",
1558 : : session_id);
1559 : 0 : return sess_idx;
1560 : : }
1561 : :
1562 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1563 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n",
1564 : : sess_idx);
1565 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1566 : : }
1567 : :
1568 [ # # ]: 0 : entry = cfa_tcam_mgr_entry_get(sess_idx, parms->id);
1569 [ # # ]: 0 : if (entry == NULL) {
1570 : 0 : CFA_TCAM_MGR_LOG(ERR, "Entry %d not found.\n", parms->id);
1571 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1572 : : }
1573 : :
1574 : 0 : table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type];
1575 : 0 : parms->hcapi_type = table_data->hcapi_type;
1576 : :
1577 : : row_size = cfa_tcam_mgr_row_size_get(sess_idx, parms->dir, parms->type);
1578 : 0 : row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, entry->row,
1579 : : row_size);
1580 : :
1581 : 0 : rc = cfa_tcam_mgr_entry_get_msg(sess_idx, context, parms,
1582 : : entry->row,
1583 : 0 : entry->slice * row->entry_size,
1584 : : table_data->max_slices);
1585 [ # # ]: 0 : if (rc < 0) {
1586 : 0 : CFA_TCAM_MGR_LOG_0(ERR, "Failed to read from TCAM.\n");
1587 : 0 : return rc;
1588 : : }
1589 : :
1590 : : return 0;
1591 : : }
1592 : :
1593 : 0 : int cfa_tcam_mgr_shared_clear(struct cfa_tcam_mgr_context *context,
1594 : : struct cfa_tcam_mgr_shared_clear_parms *parms)
1595 : : {
1596 : : int rc;
1597 : : uint16_t row, slice = 0;
1598 : : int sess_idx;
1599 : : uint32_t session_id;
1600 : : struct cfa_tcam_mgr_free_parms fparms;
1601 : : struct cfa_tcam_mgr_table_data *table_data;
1602 : : uint16_t start_row, end_row, max_entries, max_slices;
1603 : :
1604 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1605 : :
1606 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1607 [ # # ]: 0 : if (rc < 0)
1608 : : return rc;
1609 : :
1610 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1611 [ # # ]: 0 : if (sess_idx < 0) {
1612 : 0 : CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n",
1613 : : session_id);
1614 : 0 : return sess_idx;
1615 : : }
1616 : :
1617 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1618 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n",
1619 : : sess_idx);
1620 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1621 : : }
1622 : :
1623 : 0 : table_data = &cfa_tcam_mgr_tables[sess_idx][parms->dir][parms->type];
1624 : 0 : fparms.dir = parms->dir;
1625 : 0 : fparms.type = parms->type;
1626 : 0 : fparms.hcapi_type = table_data->hcapi_type;
1627 : 0 : fparms.id = 0;
1628 : :
1629 : 0 : rc = cfa_tcam_mgr_tables_get(sess_idx, parms->dir, parms->type,
1630 : : &start_row, &end_row, &max_entries, &max_slices);
1631 [ # # ]: 0 : if (rc)
1632 : : return rc;
1633 : :
1634 [ # # ]: 0 : for (row = start_row; row <= end_row; row++) {
1635 : 0 : cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms,
1636 : : row,
1637 : : slice,
1638 : 0 : table_data->row_width,
1639 : 0 : table_data->result_size,
1640 : 0 : table_data->max_slices);
1641 : : }
1642 : : return rc;
1643 : : }
1644 : :
1645 : : static void
1646 : : cfa_tcam_mgr_mv_used_entries_cnt(int sess_idx, enum tf_dir dir,
1647 : : struct cfa_tcam_mgr_table_data *dst_table_data,
1648 : : struct cfa_tcam_mgr_table_data *src_table_data)
1649 : : {
1650 : 0 : dst_table_data->used_entries++;
1651 : 0 : src_table_data->used_entries--;
1652 : :
1653 : 0 : cfa_tcam_mgr_mv_session_used_entries_cnt(sess_idx, dir,
1654 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS,
1655 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS);
1656 : : }
1657 : :
1658 : : /*
1659 : : * Move HI WC TCAM entries to LOW TCAM region for HA
1660 : : * This happens when secondary is becoming primary
1661 : : */
1662 : : static int
1663 : 0 : cfa_tcam_mgr_shared_entry_move(int sess_idx, struct cfa_tcam_mgr_context *context,
1664 : : enum tf_dir dir, enum cfa_tcam_mgr_tbl_type type,
1665 : : int entry_id,
1666 : : struct cfa_tcam_mgr_table_data *dst_table_data,
1667 : : struct cfa_tcam_mgr_table_data *table_data,
1668 : : int dst_row_index, int dst_row_slice,
1669 : : struct cfa_tcam_mgr_table_rows_0 *dst_row,
1670 : : int src_row_index,
1671 : : struct cfa_tcam_mgr_table_rows_0 *src_row)
1672 : : {
1673 : 0 : struct cfa_tcam_mgr_get_parms gparms = { 0 };
1674 : 0 : struct cfa_tcam_mgr_set_parms sparms = { 0 };
1675 : 0 : struct cfa_tcam_mgr_free_parms fparms = { 0 };
1676 : : struct cfa_tcam_mgr_entry_data *entry;
1677 : : uint8_t key[CFA_TCAM_MGR_MAX_KEY_SIZE];
1678 : : uint8_t mask[CFA_TCAM_MGR_MAX_KEY_SIZE];
1679 : : uint8_t result[CFA_TCAM_MGR_MAX_KEY_SIZE];
1680 : :
1681 : : int rc;
1682 : :
1683 [ # # ]: 0 : entry = cfa_tcam_mgr_entry_get(sess_idx, entry_id);
1684 [ # # ]: 0 : if (entry == NULL)
1685 : : return -1;
1686 : :
1687 : 0 : gparms.dir = dir;
1688 : 0 : gparms.type = type;
1689 : 0 : gparms.hcapi_type = table_data->hcapi_type;
1690 : 0 : gparms.key = key;
1691 : 0 : gparms.mask = mask;
1692 : 0 : gparms.result = result;
1693 : 0 : gparms.id = src_row->entries[entry->slice];
1694 : 0 : gparms.key_size = sizeof(key);
1695 : 0 : gparms.result_size = sizeof(result);
1696 : :
1697 : 0 : rc = cfa_tcam_mgr_entry_get_msg(sess_idx, context, &gparms,
1698 : : src_row_index,
1699 : 0 : entry->slice * src_row->entry_size,
1700 : 0 : table_data->max_slices);
1701 [ # # ]: 0 : if (rc != 0)
1702 : : return rc;
1703 : :
1704 : 0 : sparms.dir = dir;
1705 : 0 : sparms.type = CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS;
1706 : 0 : sparms.hcapi_type = table_data->hcapi_type;
1707 : 0 : sparms.key = key;
1708 : 0 : sparms.mask = mask;
1709 : 0 : sparms.result = result;
1710 : 0 : sparms.id = gparms.id;
1711 : 0 : sparms.key_size = gparms.key_size;
1712 : 0 : sparms.result_size = gparms.result_size;
1713 : :
1714 : 0 : rc = cfa_tcam_mgr_entry_set_msg(sess_idx, context, &sparms,
1715 : : dst_row_index,
1716 : 0 : dst_row_slice * dst_row->entry_size,
1717 : 0 : table_data->max_slices);
1718 [ # # ]: 0 : if (rc != 0)
1719 : : return rc;
1720 : :
1721 : 0 : fparms.dir = dir;
1722 : 0 : fparms.type = type;
1723 : 0 : fparms.hcapi_type = table_data->hcapi_type;
1724 : 0 : rc = cfa_tcam_mgr_entry_free_msg(sess_idx, context, &fparms,
1725 : : src_row_index,
1726 : 0 : entry->slice *
1727 : 0 : dst_row->entry_size,
1728 : 0 : table_data->row_width /
1729 : : table_data->max_slices *
1730 : 0 : src_row->entry_size,
1731 : 0 : table_data->result_size,
1732 : 0 : table_data->max_slices);
1733 [ # # ]: 0 : if (rc != 0) {
1734 : 0 : CFA_TCAM_MGR_LOG_DIR_TYPE(ERR,
1735 : : dir, type,
1736 : : "Failed to free entry ID %d at"
1737 : : " row %d, slice %d for sess_idx %d. rc: %d.\n",
1738 : : gparms.id,
1739 : : src_row_index,
1740 : : entry->slice,
1741 : : sess_idx,
1742 : : -rc);
1743 : : }
1744 : :
1745 : : #ifdef CFA_TCAM_MGR_TRACING
1746 : : CFA_TCAM_MGR_TRACE(INFO, "Moved entry %d from row %d, slice %d to "
1747 : : "row %d, slice %d.\n",
1748 : : entry_id, src_row_index, entry->slice,
1749 : : dst_row_index, dst_row_slice);
1750 : : #endif
1751 : :
1752 : 0 : ROW_ENTRY_SET(dst_row, dst_row_slice);
1753 : 0 : dst_row->entries[dst_row_slice] = entry_id;
1754 : 0 : dst_row->entry_size = src_row->entry_size;
1755 : 0 : dst_row->priority = src_row->priority;
1756 : 0 : ROW_ENTRY_CLEAR(src_row, entry->slice);
1757 : 0 : entry->row = dst_row_index;
1758 : 0 : entry->slice = dst_row_slice;
1759 : :
1760 : : cfa_tcam_mgr_mv_used_entries_cnt(sess_idx, dir, dst_table_data, table_data);
1761 : :
1762 : : #ifdef CFA_TCAM_MGR_TRACING
1763 : : cfa_tcam_mgr_rows_dump(sess_idx, dir, type);
1764 : : cfa_tcam_mgr_rows_dump(sess_idx, dir, CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS);
1765 : : #endif
1766 : :
1767 : 0 : return 0;
1768 : : }
1769 : :
1770 : 0 : int cfa_tcam_mgr_shared_move(struct cfa_tcam_mgr_context *context,
1771 : : struct cfa_tcam_mgr_shared_move_parms *parms)
1772 : : {
1773 : : int rc;
1774 : : int sess_idx;
1775 : : uint32_t session_id;
1776 : : uint16_t src_row, dst_row, row_size, slice;
1777 : : struct cfa_tcam_mgr_table_rows_0 *src_table_row;
1778 : : struct cfa_tcam_mgr_table_rows_0 *dst_table_row;
1779 : : struct cfa_tcam_mgr_table_data *src_table_data;
1780 : : struct cfa_tcam_mgr_table_data *dst_table_data;
1781 : :
1782 [ # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS2(context, parms);
1783 : :
1784 : 0 : rc = cfa_tcam_mgr_get_session_from_context(context, &session_id);
1785 [ # # ]: 0 : if (rc < 0)
1786 : : return rc;
1787 : :
1788 : 0 : sess_idx = cfa_tcam_mgr_session_find(session_id);
1789 [ # # ]: 0 : if (sess_idx < 0) {
1790 : 0 : CFA_TCAM_MGR_LOG(ERR, "Session 0x%08x not found.\n",
1791 : : session_id);
1792 : 0 : return sess_idx;
1793 : : }
1794 : :
1795 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1796 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: No TCAM data created for sess_idx %d\n",
1797 : : sess_idx);
1798 : 0 : return -CFA_TCAM_MGR_ERR_CODE(PERM);
1799 : : }
1800 : :
1801 : 0 : src_table_data =
1802 : 0 : &cfa_tcam_mgr_tables[sess_idx][parms->dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS];
1803 : 0 : dst_table_data =
1804 : : &cfa_tcam_mgr_tables[sess_idx][parms->dir][CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_LOW_APPS];
1805 : :
1806 : : row_size =
1807 : : cfa_tcam_mgr_row_size_get(sess_idx,
1808 : : parms->dir,
1809 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS);
1810 : :
1811 : 0 : for (src_row = src_table_data->start_row,
1812 : 0 : dst_row = dst_table_data->start_row;
1813 [ # # ]: 0 : src_row <= src_table_data->end_row;
1814 : 0 : src_row++, dst_row++) {
1815 : 0 : src_table_row = cfa_tcam_mgr_row_ptr_get(src_table_data->tcam_rows,
1816 : : src_row, row_size);
1817 : 0 : dst_table_row = cfa_tcam_mgr_row_ptr_get(dst_table_data->tcam_rows,
1818 : : dst_row, row_size);
1819 [ # # ]: 0 : if (ROW_INUSE(src_table_row)) {
1820 : : for (slice = 0;
1821 [ # # ]: 0 : slice < src_table_data->max_slices / src_table_row->entry_size;
1822 : 0 : slice++) {
1823 [ # # ]: 0 : if (ROW_ENTRY_INUSE(src_table_row, slice)) {
1824 : : #ifdef CFA_TCAM_MGR_TRACING
1825 : : CFA_TCAM_MGR_TRACE(INFO, "Move entry id %d "
1826 : : "from src_row %d, slice %d "
1827 : : "to dst_row %d, slice %d.\n",
1828 : : src_table_row->entries[slice],
1829 : : src_row, slice,
1830 : : dst_row, slice);
1831 : : #endif
1832 : 0 : rc = cfa_tcam_mgr_shared_entry_move(sess_idx,
1833 : : context,
1834 : : parms->dir,
1835 : : CFA_TCAM_MGR_TBL_TYPE_WC_TCAM_HIGH_APPS,
1836 : 0 : src_table_row->entries[slice],
1837 : : dst_table_data,
1838 : : src_table_data,
1839 : : dst_row, slice,
1840 : : dst_table_row,
1841 : : src_row,
1842 : : src_table_row);
1843 : : }
1844 : : }
1845 : : }
1846 : : }
1847 : :
1848 : : return rc;
1849 : : }
1850 : :
1851 : : static void
1852 : : cfa_tcam_mgr_tbl_get(int sess_idx, enum tf_dir dir,
1853 : : enum cfa_tcam_mgr_tbl_type type,
1854 : : uint16_t *start_row,
1855 : : uint16_t *end_row,
1856 : : uint16_t *max_entries,
1857 : : uint16_t *slices)
1858 : : {
1859 : : struct cfa_tcam_mgr_table_data *table_data =
1860 : : &cfa_tcam_mgr_tables[sess_idx][dir][type];
1861 : :
1862 : : /* Get start, end and max for tcam type*/
1863 : 0 : *start_row = table_data->start_row;
1864 : 0 : *end_row = table_data->end_row;
1865 : 0 : *max_entries = table_data->max_entries;
1866 : 0 : *slices = table_data->max_slices;
1867 : : }
1868 : :
1869 : : int
1870 : 0 : cfa_tcam_mgr_tables_get(int sess_idx, enum tf_dir dir,
1871 : : enum cfa_tcam_mgr_tbl_type type,
1872 : : uint16_t *start_row,
1873 : : uint16_t *end_row,
1874 : : uint16_t *max_entries,
1875 : : uint16_t *slices)
1876 : : {
1877 [ # # # # ]: 0 : CFA_TCAM_MGR_CHECK_PARMS3(start_row, end_row, max_entries);
1878 : :
1879 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1880 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: TCAM not initialized for sess_idx %d.\n",
1881 : : sess_idx);
1882 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1883 : : }
1884 : :
1885 [ # # ]: 0 : if (dir >= TF_DIR_MAX) {
1886 : 0 : CFA_TCAM_MGR_LOG(ERR, "Must specify valid dir (0-%d) forsess_idx %d.\n",
1887 : : TF_DIR_MAX - 1, sess_idx);
1888 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1889 : : }
1890 : :
1891 [ # # ]: 0 : if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) {
1892 : 0 : CFA_TCAM_MGR_LOG(ERR, "Must specify valid tbl type (0-%d) forsess_idx %d.\n",
1893 : : CFA_TCAM_MGR_TBL_TYPE_MAX - 1, sess_idx);
1894 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1895 : : }
1896 : :
1897 : : cfa_tcam_mgr_tbl_get(sess_idx, dir,
1898 : : type,
1899 : : start_row,
1900 : : end_row,
1901 : : max_entries,
1902 : : slices);
1903 : 0 : return 0;
1904 : : }
1905 : :
1906 : : static void
1907 : : cfa_tcam_mgr_tbl_set(int sess_idx, enum tf_dir dir,
1908 : : enum cfa_tcam_mgr_tbl_type type,
1909 : : uint16_t start_row,
1910 : : uint16_t end_row,
1911 : : uint16_t max_entries)
1912 : : {
1913 : : struct cfa_tcam_mgr_table_data *table_data =
1914 : : &cfa_tcam_mgr_tables[sess_idx][dir][type];
1915 : :
1916 : : /* Update start, end and max for tcam type*/
1917 : 0 : table_data->start_row = start_row;
1918 : 0 : table_data->end_row = end_row;
1919 : 0 : table_data->max_entries = max_entries;
1920 : : }
1921 : :
1922 : : int
1923 : 0 : cfa_tcam_mgr_tables_set(int sess_idx, enum tf_dir dir,
1924 : : enum cfa_tcam_mgr_tbl_type type,
1925 : : uint16_t start_row,
1926 : : uint16_t end_row,
1927 : : uint16_t max_entries)
1928 : : {
1929 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1930 : 0 : CFA_TCAM_MGR_LOG(ERR, "PANIC: TCAM not initialized for sess_idx %d.\n",
1931 : : sess_idx);
1932 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1933 : : }
1934 : :
1935 [ # # ]: 0 : if (dir >= TF_DIR_MAX) {
1936 : 0 : CFA_TCAM_MGR_LOG(ERR, "Must specify valid dir (0-%d) forsess_idx %d.\n",
1937 : : TF_DIR_MAX - 1, sess_idx);
1938 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1939 : : }
1940 : :
1941 [ # # ]: 0 : if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) {
1942 : 0 : CFA_TCAM_MGR_LOG(ERR, "Must specify valid tbl type (0-%d) forsess_idx %d.\n",
1943 : : CFA_TCAM_MGR_TBL_TYPE_MAX - 1, sess_idx);
1944 : 0 : return -CFA_TCAM_MGR_ERR_CODE(INVAL);
1945 : : }
1946 : :
1947 : : cfa_tcam_mgr_tbl_set(sess_idx, dir,
1948 : : type,
1949 : : start_row,
1950 : : end_row,
1951 : : max_entries);
1952 : 0 : return 0;
1953 : : }
1954 : :
1955 : : void
1956 : 0 : cfa_tcam_mgr_rows_dump(int sess_idx, enum tf_dir dir,
1957 : : enum cfa_tcam_mgr_tbl_type type)
1958 : : {
1959 : : struct cfa_tcam_mgr_table_data *table_data;
1960 : : struct cfa_tcam_mgr_table_rows_0 *table_row;
1961 : : int i, row, row_size;
1962 : : bool row_found = false;
1963 : : bool empty_row = false;
1964 : :
1965 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
1966 : : printf("PANIC: TCAM not initialized for sess_idx %d.\n", sess_idx);
1967 : 0 : return;
1968 : : }
1969 : :
1970 [ # # ]: 0 : if (dir >= TF_DIR_MAX) {
1971 : : printf("Must specify a valid direction (0-%d).\n",
1972 : : TF_DIR_MAX - 1);
1973 : 0 : return;
1974 : : }
1975 [ # # ]: 0 : if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) {
1976 : : printf("Must specify a valid type (0-%d).\n",
1977 : : CFA_TCAM_MGR_TBL_TYPE_MAX - 1);
1978 : 0 : return;
1979 : : }
1980 : :
1981 : : table_data = &cfa_tcam_mgr_tables[sess_idx][dir][type];
1982 : : row_size = cfa_tcam_mgr_row_size_get(sess_idx, dir, type);
1983 : :
1984 : : printf("\nTCAM Rows:\n");
1985 : 0 : printf("Rows for direction %s, Logical table type %s\n",
1986 : : tf_dir_2_str(dir), cfa_tcam_mgr_tbl_2_str(type));
1987 : 0 : printf("Managed rows %d-%d for sess_idx %d:\n",
1988 : 0 : table_data->start_row, table_data->end_row, sess_idx);
1989 : :
1990 : : printf("Index Pri Size Entry IDs\n");
1991 : : printf(" Sl 0");
1992 [ # # ]: 0 : for (i = 1; i < table_data->max_slices; i++)
1993 : : printf(" Sl %d", i);
1994 : : printf("\n");
1995 [ # # ]: 0 : for (row = table_data->start_row; row <= table_data->end_row; row++) {
1996 : 0 : table_row = cfa_tcam_mgr_row_ptr_get(table_data->tcam_rows, row,
1997 : : row_size);
1998 [ # # ]: 0 : if (ROW_INUSE(table_row)) {
1999 : : empty_row = false;
2000 : 0 : printf("%5u %5u %4u",
2001 : : row,
2002 : 0 : TF_TCAM_PRIORITY_MAX - table_row->priority - 1,
2003 : 0 : table_row->entry_size);
2004 : 0 : for (i = 0;
2005 [ # # ]: 0 : i < table_data->max_slices / table_row->entry_size;
2006 : 0 : i++) {
2007 [ # # ]: 0 : if (ROW_ENTRY_INUSE(table_row, i))
2008 : 0 : printf(" %5u", table_row->entries[i]);
2009 : : else
2010 : : printf(" x");
2011 : : }
2012 : : printf("\n");
2013 : : row_found = true;
2014 [ # # ]: 0 : } else if (!empty_row) {
2015 : : empty_row = true;
2016 : : printf("\n");
2017 : : }
2018 : : }
2019 : :
2020 [ # # ]: 0 : if (!row_found)
2021 : : printf("No rows in use.\n");
2022 : : }
2023 : :
2024 : : static void
2025 : 0 : cfa_tcam_mgr_table_dump(int sess_idx, enum tf_dir dir,
2026 : : enum cfa_tcam_mgr_tbl_type type)
2027 : : {
2028 : : struct cfa_tcam_mgr_table_data *table_data =
2029 : : &cfa_tcam_mgr_tables[sess_idx][dir][type];
2030 : :
2031 : 0 : printf("%3s %-22s %5u %5u %5u %5u %6u %7u %2u\n",
2032 : : tf_dir_2_str(dir),
2033 : : cfa_tcam_mgr_tbl_2_str(type),
2034 : 0 : table_data->row_width,
2035 : 0 : table_data->num_rows,
2036 : 0 : table_data->start_row,
2037 : 0 : table_data->end_row,
2038 : 0 : table_data->max_entries,
2039 : 0 : table_data->used_entries,
2040 : 0 : table_data->max_slices);
2041 : 0 : }
2042 : :
2043 : : #define TABLE_DUMP_HEADER \
2044 : : "Dir Table Width Rows Start End " \
2045 : : "MaxEnt UsedEnt Slices\n"
2046 : :
2047 : : void
2048 : 0 : cfa_tcam_mgr_tables_dump(int sess_idx, enum tf_dir dir,
2049 : : enum cfa_tcam_mgr_tbl_type type)
2050 : : {
2051 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
2052 : : printf("PANIC: TCAM not initialized for sess_idx %d.\n", sess_idx);
2053 : 0 : return;
2054 : : }
2055 : :
2056 : : printf("\nTCAM Table(s) for sess_idx %d:\n", sess_idx);
2057 : : printf(TABLE_DUMP_HEADER);
2058 [ # # ]: 0 : if (dir >= TF_DIR_MAX) {
2059 : : /* Iterate over all directions */
2060 [ # # ]: 0 : for (dir = 0; dir < TF_DIR_MAX; dir++) {
2061 [ # # ]: 0 : if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) {
2062 : : /* Iterate over all types */
2063 : : for (type = 0;
2064 [ # # ]: 0 : type < CFA_TCAM_MGR_TBL_TYPE_MAX;
2065 : 0 : type++) {
2066 : 0 : cfa_tcam_mgr_table_dump(sess_idx, dir, type);
2067 : : }
2068 : : } else {
2069 : : /* Display a specific type */
2070 : 0 : cfa_tcam_mgr_table_dump(sess_idx, dir, type);
2071 : : }
2072 : : }
2073 [ # # ]: 0 : } else if (type >= CFA_TCAM_MGR_TBL_TYPE_MAX) {
2074 : : /* Iterate over all types for a direction */
2075 [ # # ]: 0 : for (type = 0; type < CFA_TCAM_MGR_TBL_TYPE_MAX; type++)
2076 : 0 : cfa_tcam_mgr_table_dump(sess_idx, dir, type);
2077 : : } else {
2078 : : /* Display a specific direction and type */
2079 : 0 : cfa_tcam_mgr_table_dump(sess_idx, dir, type);
2080 : : }
2081 : : }
2082 : :
2083 : : #define ENTRY_DUMP_HEADER "Entry RefCnt Row Slice\n"
2084 : :
2085 : : void
2086 : 0 : cfa_tcam_mgr_entries_dump(int sess_idx)
2087 : : {
2088 : : struct cfa_tcam_mgr_entry_data *entry;
2089 : : bool entry_found = false;
2090 : : uint16_t id;
2091 : :
2092 [ # # ]: 0 : if (global_data_initialized[sess_idx] == 0) {
2093 : 0 : CFA_TCAM_MGR_LOG(INFO, "PANIC: No TCAM data created for sess_idx %d\n",
2094 : : sess_idx);
2095 : 0 : return;
2096 : : }
2097 : :
2098 : 0 : printf("\nGlobal Maximum Entries: %d\n\n",
2099 : : cfa_tcam_mgr_max_entries[sess_idx]);
2100 : : printf("TCAM Entry Table:\n");
2101 [ # # ]: 0 : for (id = 0; id < cfa_tcam_mgr_max_entries[sess_idx]; id++) {
2102 [ # # ]: 0 : if (entry_data[sess_idx][id].ref_cnt > 0) {
2103 : : entry = &entry_data[sess_idx][id];
2104 [ # # ]: 0 : if (!entry_found)
2105 : : printf(ENTRY_DUMP_HEADER);
2106 : 0 : printf("%5u %5u %5u %5u",
2107 : 0 : id, entry->ref_cnt,
2108 : 0 : entry->row, entry->slice);
2109 : : printf("\n");
2110 : : entry_found = true;
2111 : : }
2112 : : }
2113 : :
2114 [ # # ]: 0 : if (!entry_found)
2115 : : printf("No entries found.\n");
2116 : : }
|