net/bnxt: update compute field list and access macros
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_mapper.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "bnxt.h"
9 #include "ulp_template_db.h"
10 #include "ulp_template_struct.h"
11 #include "bnxt_tf_common.h"
12 #include "ulp_utils.h"
13 #include "bnxt_ulp.h"
14 #include "tfp.h"
15 #include "tf_ext_flow_handle.h"
16 #include "ulp_mark_mgr.h"
17 #include "ulp_flow_db.h"
18 #include "ulp_mapper.h"
19
20 static struct bnxt_ulp_def_ident_info *
21 ulp_mapper_def_ident_info_list_get(uint32_t *num_entries)
22 {
23         if (!num_entries)
24                 return NULL;
25         *num_entries = BNXT_ULP_DEF_IDENT_INFO_TBL_MAX_SZ;
26         return ulp_def_ident_tbl;
27 }
28
29 /*
30  * Read a default identifier from the mapper regfile.
31  *
32  * The regval is always returned in big-endian.
33  *
34  * returns 0 on success
35  */
36 static int32_t
37 ulp_mapper_def_regfile_read(struct bnxt_ulp_mapper_data *mapper_data,
38                             enum tf_dir dir,
39                             uint16_t idx,
40                             uint64_t *regval)
41 {
42         if (!mapper_data || !regval ||
43             dir >= TF_DIR_MAX || idx >= BNXT_ULP_DEF_REGFILE_INDEX_LAST)
44                 return -EINVAL;
45         *regval = mapper_data->dflt_ids[dir][idx].ident;
46         return 0;
47 }
48
49 /*
50  * Write a default identifier to the mapper regfile
51  *
52  * The regval value must be in big-endian.
53  *
54  * return 0 on success.
55  */
56 static int32_t
57 ulp_mapper_def_regfile_write(struct bnxt_ulp_mapper_data *mapper_data,
58                              enum tf_dir dir,
59                              uint16_t idx,
60                              uint64_t regval)
61 {
62         if (!mapper_data || dir >= TF_DIR_MAX ||
63             idx >= BNXT_ULP_DEF_REGFILE_INDEX_LAST)
64                 return -EINVAL;
65         mapper_data->dflt_ids[dir][idx].ident = regval;
66         return 0;
67 }
68
69 /* Retrieve the cache initialization parameters for the tbl_idx */
70 static struct bnxt_ulp_cache_tbl_params *
71 ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx)
72 {
73         if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ)
74                 return NULL;
75
76         return &ulp_cache_tbl_params[tbl_idx];
77 }
78
79 /*
80  * Get the size of the action property for a given index.
81  *
82  * idx [in] The index for the action property
83  *
84  * returns the size of the action property.
85  */
86 static uint32_t
87 ulp_mapper_act_prop_size_get(uint32_t idx)
88 {
89         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
90                 return 0;
91         return ulp_act_prop_map_table[idx];
92 }
93
94 /*
95  * Get the list of result fields that implement the flow action.
96  * Gets a device dependent list of tables that implement the action template id.
97  *
98  * dev_id [in] The device id of the forwarding element
99  *
100  * tid [in] The action template id that matches the flow
101  *
102  * num_tbls [out] The number of action tables in the returned array
103  *
104  * Returns An array of action tables to implement the flow, or NULL on error.
105  */
106 static struct bnxt_ulp_mapper_act_tbl_info *
107 ulp_mapper_action_tbl_list_get(uint32_t dev_id,
108                                uint32_t tid,
109                                uint32_t *num_tbls)
110 {
111         uint32_t        idx;
112         uint32_t        tidx;
113
114         if (!num_tbls) {
115                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
116                 return NULL;
117         }
118
119         /* template shift and device mask */
120         tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
121
122         /* NOTE: Need to have something from template compiler to help validate
123          * range of dev_id and act_tid
124          */
125         idx             = ulp_act_tmpl_list[tidx].start_tbl_idx;
126         *num_tbls       = ulp_act_tmpl_list[tidx].num_tbls;
127
128         return &ulp_act_tbl_list[idx];
129 }
130
131 /** Get a list of classifier tables that implement the flow
132  * Gets a device dependent list of tables that implement the class template id
133  *
134  * dev_id [in] The device id of the forwarding element
135  *
136  * tid [in] The template id that matches the flow
137  *
138  * num_tbls [out] The number of classifier tables in the returned array
139  *
140  * returns An array of classifier tables to implement the flow, or NULL on
141  * error
142  */
143 static struct bnxt_ulp_mapper_class_tbl_info *
144 ulp_mapper_class_tbl_list_get(uint32_t dev_id,
145                               uint32_t tid,
146                               uint32_t *num_tbls)
147 {
148         uint32_t idx;
149         uint32_t tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
150
151         if (!num_tbls)
152                 return NULL;
153
154         /* NOTE: Need to have something from template compiler to help validate
155          * range of dev_id and tid
156          */
157         idx             = ulp_class_tmpl_list[tidx].start_tbl_idx;
158         *num_tbls       = ulp_class_tmpl_list[tidx].num_tbls;
159
160         return &ulp_class_tbl_list[idx];
161 }
162
163 /*
164  * Get the list of key fields that implement the flow.
165  *
166  * ctxt [in] The ulp context
167  *
168  * tbl [in] A single table instance to get the key fields from
169  *
170  * num_flds [out] The number of key fields in the returned array
171  *
172  * Returns array of Key fields, or NULL on error.
173  */
174 static struct bnxt_ulp_mapper_class_key_field_info *
175 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
176                           uint32_t *num_flds)
177 {
178         uint32_t idx;
179
180         if (!tbl || !num_flds)
181                 return NULL;
182
183         idx             = tbl->key_start_idx;
184         *num_flds       = tbl->key_num_fields;
185
186         /* NOTE: Need template to provide range checking define */
187         return &ulp_class_key_field_list[idx];
188 }
189
190 /*
191  * Get the list of data fields that implement the flow.
192  *
193  * ctxt [in] The ulp context
194  *
195  * tbl [in] A single table instance to get the data fields from
196  *
197  * num_flds [out] The number of data fields in the returned array.
198  *
199  * Returns array of data fields, or NULL on error.
200  */
201 static struct bnxt_ulp_mapper_result_field_info *
202 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
203                              uint32_t *num_flds)
204 {
205         uint32_t idx;
206
207         if (!tbl || !num_flds)
208                 return NULL;
209
210         idx             = tbl->result_start_idx;
211         *num_flds       = tbl->result_num_fields;
212
213         /* NOTE: Need template to provide range checking define */
214         return &ulp_class_result_field_list[idx];
215 }
216
217 /*
218  * Get the list of result fields that implement the flow action.
219  *
220  * tbl [in] A single table instance to get the results fields
221  * from num_flds [out] The number of data fields in the returned
222  * array.
223  *
224  * Returns array of data fields, or NULL on error.
225  */
226 static struct bnxt_ulp_mapper_result_field_info *
227 ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_act_tbl_info *tbl,
228                                  uint32_t *num_rslt_flds,
229                                  uint32_t *num_encap_flds)
230 {
231         uint32_t idx;
232
233         if (!tbl || !num_rslt_flds || !num_encap_flds)
234                 return NULL;
235
236         idx             = tbl->result_start_idx;
237         *num_rslt_flds  = tbl->result_num_fields;
238         *num_encap_flds = tbl->encap_num_fields;
239
240         /* NOTE: Need template to provide range checking define */
241         return &ulp_act_result_field_list[idx];
242 }
243
244 /*
245  * Get the list of ident fields that implement the flow
246  *
247  * tbl [in] A single table instance to get the ident fields from
248  *
249  * num_flds [out] The number of ident fields in the returned array
250  *
251  * returns array of ident fields, or NULL on error
252  */
253 static struct bnxt_ulp_mapper_ident_info *
254 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
255                             uint32_t *num_flds)
256 {
257         uint32_t idx;
258
259         if (!tbl || !num_flds)
260                 return NULL;
261
262         idx = tbl->ident_start_idx;
263         *num_flds = tbl->ident_nums;
264
265         /* NOTE: Need template to provide range checking define */
266         return &ulp_ident_list[idx];
267 }
268
269 static struct bnxt_ulp_mapper_cache_entry *
270 ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp,
271                            enum bnxt_ulp_cache_tbl_id id,
272                            uint16_t key)
273 {
274         struct bnxt_ulp_mapper_data *mapper_data;
275
276         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp);
277         if (!mapper_data || !mapper_data->cache_tbl[id]) {
278                 BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id);
279                 return NULL;
280         }
281
282         return &mapper_data->cache_tbl[id][key];
283 }
284
285 /*
286  * Concatenates the tbl_type and tbl_id into a 32bit value for storing in the
287  * resource_type.  This is done to conserve memory since both the tbl_type and
288  * tbl_id are 16bit.
289  */
290 static inline void
291 ulp_mapper_cache_res_type_set(struct ulp_flow_db_res_params *res,
292                               uint16_t tbl_type,
293                               uint16_t tbl_id)
294 {
295         res->resource_type = tbl_type;
296         res->resource_sub_type = tbl_id;
297 }
298
299 /* Extracts the tbl_type and tbl_id from the 32bit resource type. */
300 static inline void
301 ulp_mapper_cache_res_type_get(struct ulp_flow_db_res_params *res,
302                               uint16_t *tbl_type,
303                               uint16_t *tbl_id)
304 {
305         *tbl_type = res->resource_type;
306         *tbl_id = res->resource_sub_type;
307 }
308
309 static int32_t
310 ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp,
311                            struct tf *tfp,
312                            struct ulp_flow_db_res_params *res)
313 {
314         struct bnxt_ulp_mapper_cache_entry *cache_entry;
315         struct tf_free_identifier_parms ident_parms;
316         struct tf_free_tcam_entry_parms tcam_parms;
317         uint16_t table_id, table_type;
318         int32_t rc, trc, i;
319
320         /*
321          * The table id, used for cache, and table_type, used for tcam, are
322          * both encoded within the resource.  We must first extract them to
323          * formulate the args for tf calls.
324          */
325         ulp_mapper_cache_res_type_get(res, &table_type, &table_id);
326
327         cache_entry = ulp_mapper_cache_entry_get(ulp, table_id,
328                                                  (uint16_t)res->resource_hndl);
329         if (!cache_entry || !cache_entry->ref_count) {
330                 BNXT_TF_DBG(ERR, "Cache entry (%d:%d) not valid on free.\n",
331                             table_id, (uint16_t)res->resource_hndl);
332                 return -EINVAL;
333         }
334
335         /*
336          * See if we need to delete the entry.  The tcam and identifiers are all
337          * tracked by the cached entries reference count.  All are deleted when
338          * the reference count hit zero.
339          */
340         cache_entry->ref_count--;
341         if (cache_entry->ref_count)
342                 return 0;
343
344         /*
345          * Need to delete the tcam entry and the allocated identifiers.
346          * In the event of a failure, need to try to delete the remaining
347          * resources before returning error.
348          */
349         tcam_parms.dir = res->direction;
350         tcam_parms.tcam_tbl_type = table_type;
351         tcam_parms.idx = cache_entry->tcam_idx;
352         rc = tf_free_tcam_entry(tfp, &tcam_parms);
353         if (rc)
354                 BNXT_TF_DBG(ERR, "Failed to free tcam [%d][%s][0x%04x] rc=%d\n",
355                             table_type,
356                             (res->direction == TF_DIR_RX) ? "RX" : "TX",
357                             tcam_parms.idx, rc);
358
359         /*
360          * Free the identifiers associated with the tcam entry.  Entries with
361          * negative one are considered uninitialized.
362          */
363         for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) {
364                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
365                         continue;
366
367                 ident_parms.dir = res->direction;
368                 ident_parms.ident_type = cache_entry->ident_types[i];
369                 ident_parms.id = cache_entry->idents[i];
370                 trc = tf_free_identifier(tfp, &ident_parms);
371                 if (trc) {
372                         BNXT_TF_DBG(ERR, "Failed to free identifier "
373                                     "[%d][%s][0x%04x] rc=%d\n",
374                                     ident_parms.ident_type,
375                                     (res->direction == TF_DIR_RX) ? "RX" : "TX",
376                                     ident_parms.id, trc);
377                         rc = trc;
378                 }
379         }
380
381         return rc;
382 }
383
384 static inline int32_t
385 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
386                            struct tf *tfp,
387                            struct ulp_flow_db_res_params *res)
388 {
389         struct tf_free_tcam_entry_parms fparms = {
390                 .dir            = res->direction,
391                 .tcam_tbl_type  = res->resource_type,
392                 .idx            = (uint16_t)res->resource_hndl
393         };
394
395         return tf_free_tcam_entry(tfp, &fparms);
396 }
397
398 static inline int32_t
399 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
400                             struct tf *tfp,
401                             struct ulp_flow_db_res_params *res)
402 {
403         struct tf_free_tbl_entry_parms fparms = {
404                 .dir    = res->direction,
405                 .type   = res->resource_type,
406                 .idx    = (uint32_t)res->resource_hndl
407         };
408
409         /*
410          * Just set the table scope, it will be ignored if not necessary
411          * by the tf_free_tbl_entry
412          */
413         bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
414
415         return tf_free_tbl_entry(tfp, &fparms);
416 }
417
418 static inline int32_t
419 ulp_mapper_eem_entry_free(struct bnxt_ulp_context *ulp,
420                           struct tf *tfp,
421                           struct ulp_flow_db_res_params *res)
422 {
423         struct tf_delete_em_entry_parms fparms = { 0 };
424         int32_t rc;
425
426         fparms.dir              = res->direction;
427         fparms.mem              = TF_MEM_EXTERNAL;
428         fparms.flow_handle      = res->resource_hndl;
429
430         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
431         if (rc) {
432                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
433                 return -EINVAL;
434         }
435
436         return tf_delete_em_entry(tfp, &fparms);
437 }
438
439 static inline int32_t
440 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
441                       struct tf *tfp,
442                       struct ulp_flow_db_res_params *res)
443 {
444         struct tf_free_identifier_parms fparms = {
445                 .dir            = res->direction,
446                 .ident_type     = res->resource_type,
447                 .id             = (uint16_t)res->resource_hndl
448         };
449
450         return tf_free_identifier(tfp, &fparms);
451 }
452
453 static inline int32_t
454 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
455                      struct ulp_flow_db_res_params *res)
456 {
457         return ulp_mark_db_mark_del(ulp,
458                                     res->resource_type,
459                                     res->resource_hndl);
460 }
461
462 /*
463  * Process the identifier instruction and either store it in the flow database
464  * or return it in the val (if not NULL) on success.  If val is NULL, the
465  * identifier is to be stored in the flow database.
466  */
467 static int32_t
468 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
469                          struct bnxt_ulp_mapper_class_tbl_info *tbl,
470                          struct bnxt_ulp_mapper_ident_info *ident,
471                          uint16_t *val)
472 {
473         struct ulp_flow_db_res_params   fid_parms;
474         uint64_t id = 0;
475         int32_t idx;
476         struct tf_alloc_identifier_parms iparms = { 0 };
477         struct tf_free_identifier_parms free_parms = { 0 };
478         struct tf *tfp;
479         int rc;
480
481         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
482         if (!tfp) {
483                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
484                 return -EINVAL;
485         }
486
487         idx = ident->regfile_wr_idx;
488
489         iparms.ident_type = ident->ident_type;
490         iparms.dir = tbl->direction;
491
492         rc = tf_alloc_identifier(tfp, &iparms);
493         if (rc) {
494                 BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n",
495                             (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
496                             iparms.ident_type);
497                 return rc;
498         }
499
500         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
501         if (!ulp_regfile_write(parms->regfile, idx, id)) {
502                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
503                 rc = -EINVAL;
504                 /* Need to free the identifier, so goto error */
505                 goto error;
506         }
507
508         /* Link the resource to the flow in the flow db */
509         if (!val) {
510                 memset(&fid_parms, 0, sizeof(fid_parms));
511                 fid_parms.direction             = tbl->direction;
512                 fid_parms.resource_func = ident->resource_func;
513                 fid_parms.resource_type = ident->ident_type;
514                 fid_parms.resource_hndl = iparms.id;
515                 fid_parms.critical_resource     = 0;
516
517                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
518                                               parms->tbl_idx,
519                                               parms->fid,
520                                               &fid_parms);
521                 if (rc) {
522                         BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
523                                     rc);
524                         /* Need to free the identifier, so goto error */
525                         goto error;
526                 }
527         } else {
528                 *val = iparms.id;
529         }
530
531         return 0;
532
533 error:
534         /* Need to free the identifier */
535         free_parms.dir          = tbl->direction;
536         free_parms.ident_type   = ident->ident_type;
537         free_parms.id           = iparms.id;
538
539         (void)tf_free_identifier(tfp, &free_parms);
540
541         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
542                     ident->description,
543                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX");
544         return rc;
545 }
546
547 static int32_t
548 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
549                                 enum tf_dir dir,
550                                 struct bnxt_ulp_mapper_result_field_info *fld,
551                                 struct ulp_blob *blob,
552                                 const char *name)
553 {
554         uint16_t idx, size_idx;
555         uint8_t  *val = NULL;
556         uint64_t regval;
557         uint32_t val_size = 0, field_size = 0;
558
559         switch (fld->result_opcode) {
560         case BNXT_ULP_RESULT_OPC_SET_TO_CONSTANT:
561                 val = fld->result_operand;
562                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
563                         BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
564                         return -EINVAL;
565                 }
566                 break;
567         case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP:
568                 if (!ulp_operand_read(fld->result_operand,
569                                       (uint8_t *)&idx, sizeof(uint16_t))) {
570                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
571                         return -EINVAL;
572                 }
573                 idx = tfp_be_to_cpu_16(idx);
574
575                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
576                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
577                         return -EINVAL;
578                 }
579                 val = &parms->act_prop->act_details[idx];
580                 field_size = ulp_mapper_act_prop_size_get(idx);
581                 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
582                         field_size  = field_size -
583                             ((fld->field_bit_size + 7) / 8);
584                         val += field_size;
585                 }
586                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
587                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
588                         return -EINVAL;
589                 }
590                 break;
591         case BNXT_ULP_RESULT_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
592                 if (!ulp_operand_read(fld->result_operand,
593                                       (uint8_t *)&idx, sizeof(uint16_t))) {
594                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
595                         return -EINVAL;
596                 }
597                 idx = tfp_be_to_cpu_16(idx);
598
599                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
600                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
601                         return -EINVAL;
602                 }
603                 val = &parms->act_prop->act_details[idx];
604
605                 /* get the size index next */
606                 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
607                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
608                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
609                         return -EINVAL;
610                 }
611                 size_idx = tfp_be_to_cpu_16(size_idx);
612
613                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
614                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
615                         return -EINVAL;
616                 }
617                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
618                        sizeof(uint32_t));
619                 val_size = tfp_be_to_cpu_32(val_size);
620                 val_size = ULP_BYTE_2_BITS(val_size);
621                 ulp_blob_push_encap(blob, val, val_size);
622                 break;
623         case BNXT_ULP_RESULT_OPC_SET_TO_REGFILE:
624                 if (!ulp_operand_read(fld->result_operand,
625                                       (uint8_t *)&idx, sizeof(uint16_t))) {
626                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
627                         return -EINVAL;
628                 }
629
630                 idx = tfp_be_to_cpu_16(idx);
631                 /* Uninitialized regfile entries return 0 */
632                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
633                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
634                                     name, idx);
635                         return -EINVAL;
636                 }
637
638                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
639                 if (!val) {
640                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
641                         return -EINVAL;
642                 }
643                 break;
644         case BNXT_ULP_RESULT_OPC_SET_TO_DEF_REGFILE:
645                 if (!ulp_operand_read(fld->result_operand,
646                                       (uint8_t *)&idx,
647                                       sizeof(uint16_t))) {
648                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
649                         return -EINVAL;
650                 }
651                 idx = tfp_be_to_cpu_16(idx);
652                 if (ulp_mapper_def_regfile_read(parms->mapper_data,
653                                                 dir,
654                                                 idx, &regval)) {
655                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
656                                     name, idx);
657                         return -EINVAL;
658                 }
659                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
660                 if (!val) {
661                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
662                         return -EINVAL;
663                 }
664                 break;
665         case BNXT_ULP_RESULT_OPC_SET_TO_COMP_FIELD:
666                 if (!ulp_operand_read(fld->result_operand,
667                                       (uint8_t *)&idx,
668                                       sizeof(uint16_t))) {
669                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
670                         return -EINVAL;
671                 }
672                 idx = tfp_be_to_cpu_16(idx);
673                 if (idx < BNXT_ULP_CF_IDX_LAST)
674                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
675                                                fld->field_bit_size);
676                 if (!val) {
677                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
678                         return -EINVAL;
679                 }
680                 break;
681         default:
682                 return -EINVAL;
683         }
684         return 0;
685 }
686
687 /* Function to alloc action record and set the table. */
688 static int32_t
689 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
690                                  enum tf_dir dir,
691                                  struct bnxt_ulp_mapper_class_key_field_info *f,
692                                  struct ulp_blob *blob,
693                                  uint8_t is_key,
694                                  const char *name)
695 {
696         uint64_t val64;
697         uint16_t idx, bitlen;
698         uint32_t opcode;
699         uint8_t *operand;
700         struct ulp_regfile *regfile = parms->regfile;
701         uint8_t *val = NULL;
702         struct bnxt_ulp_mapper_class_key_field_info *fld = f;
703         uint32_t field_size;
704
705         if (is_key) {
706                 operand = fld->spec_operand;
707                 opcode  = fld->spec_opcode;
708         } else {
709                 operand = fld->mask_operand;
710                 opcode  = fld->mask_opcode;
711         }
712
713         bitlen = fld->field_bit_size;
714
715         switch (opcode) {
716         case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT:
717                 val = operand;
718                 if (!ulp_blob_push(blob, val, bitlen)) {
719                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
720                         return -EINVAL;
721                 }
722                 break;
723         case BNXT_ULP_SPEC_OPC_ADD_PAD:
724                 if (!ulp_blob_pad_push(blob, bitlen)) {
725                         BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
726                         return -EINVAL;
727                 }
728
729                 break;
730         case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD:
731                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
732                                       sizeof(uint16_t))) {
733                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
734                         return -EINVAL;
735                 }
736                 idx = tfp_be_to_cpu_16(idx);
737                 if (is_key)
738                         val = parms->hdr_field[idx].spec;
739                 else
740                         val = parms->hdr_field[idx].mask;
741
742                 /*
743                  * Need to account for how much data was pushed to the header
744                  * field vs how much is to be inserted in the key/mask.
745                  */
746                 field_size = parms->hdr_field[idx].size;
747                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
748                         field_size  = field_size - ((bitlen + 7) / 8);
749                         val += field_size;
750                 }
751
752                 if (!ulp_blob_push(blob, val, bitlen)) {
753                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
754                         return -EINVAL;
755                 }
756                 break;
757         case BNXT_ULP_SPEC_OPC_SET_TO_COMP_FIELD:
758                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
759                                       sizeof(uint16_t))) {
760                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
761                         return -EINVAL;
762                 }
763                 idx = tfp_be_to_cpu_16(idx);
764                 if (idx < BNXT_ULP_CF_IDX_LAST)
765                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
766                                                bitlen);
767                 if (!val) {
768                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
769                         return -EINVAL;
770                 }
771                 break;
772         case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE:
773                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
774                                       sizeof(uint16_t))) {
775                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
776                         return -EINVAL;
777                 }
778                 idx = tfp_be_to_cpu_16(idx);
779
780                 if (!ulp_regfile_read(regfile, idx, &val64)) {
781                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
782                                     name, idx);
783                         return -EINVAL;
784                 }
785
786                 val = ulp_blob_push_64(blob, &val64, bitlen);
787                 if (!val) {
788                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
789                         return -EINVAL;
790                 }
791                 break;
792         case BNXT_ULP_SPEC_OPC_SET_TO_DEF_REGFILE:
793                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
794                                       sizeof(uint16_t))) {
795                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
796                         return -EINVAL;
797                 }
798                 idx = tfp_be_to_cpu_16(idx);
799                 if (ulp_mapper_def_regfile_read(parms->mapper_data,
800                                                 dir,
801                                                 idx, &val64)) {
802                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
803                                     name, idx);
804                         return -EINVAL;
805                 }
806                 val = ulp_blob_push_64(blob, &val64, bitlen);
807                 if (!val) {
808                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
809                         return -EINVAL;
810                 }
811                 break;
812         default:
813                 break;
814         }
815
816         return 0;
817 }
818
819 /* Function to alloc action record and set the table. */
820 static int32_t
821 ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms,
822                                 struct ulp_blob *blob)
823 {
824         struct ulp_flow_db_res_params           fid_parms;
825         struct tf_alloc_tbl_entry_parms         alloc_parms = { 0 };
826         struct tf_free_tbl_entry_parms          free_parms = { 0 };
827         struct bnxt_ulp_mapper_act_tbl_info     *atbls = parms->atbls;
828         int32_t                                 rc = 0;
829         int32_t trc;
830         uint64_t                                idx;
831         uint32_t tbl_scope_id;
832
833         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
834
835         /* Set the allocation parameters for the table*/
836         alloc_parms.dir = atbls->direction;
837         alloc_parms.type = atbls->table_type;
838         alloc_parms.search_enable = atbls->srch_b4_alloc;
839         alloc_parms.result = ulp_blob_data_get(blob,
840                                                &alloc_parms.result_sz_in_bytes);
841         alloc_parms.tbl_scope_id = tbl_scope_id;
842         if (!alloc_parms.result) {
843                 BNXT_TF_DBG(ERR, "blob is not populated\n");
844                 return -EINVAL;
845         }
846
847         rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms);
848         if (rc) {
849                 BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n",
850                             alloc_parms.type,
851                             (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX");
852                 return rc;
853         }
854
855         /* Need to calculate the idx for the result record */
856         uint64_t tmpidx = alloc_parms.idx;
857
858         if (atbls->table_type == TF_TBL_TYPE_EXT)
859                 tmpidx = TF_ACT_REC_OFFSET_2_PTR(alloc_parms.idx);
860         else
861                 tmpidx = alloc_parms.idx;
862
863         idx = tfp_cpu_to_be_64(tmpidx);
864
865         /* Store the allocated index for future use in the regfile */
866         rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx);
867         if (!rc) {
868                 BNXT_TF_DBG(ERR, "regfile[%d] write failed\n",
869                             atbls->regfile_wr_idx);
870                 rc = -EINVAL;
871                 goto error;
872         }
873
874         /*
875          * The set_tbl_entry API if search is not enabled or searched entry
876          * is not found.
877          */
878         if (!atbls->srch_b4_alloc || !alloc_parms.hit) {
879                 struct tf_set_tbl_entry_parms set_parm = { 0 };
880                 uint16_t        length;
881
882                 set_parm.dir    = atbls->direction;
883                 set_parm.type   = atbls->table_type;
884                 set_parm.idx    = alloc_parms.idx;
885                 set_parm.data   = ulp_blob_data_get(blob, &length);
886                 set_parm.data_sz_in_bytes = length / 8;
887
888                 if (set_parm.type == TF_TBL_TYPE_EXT)
889                         set_parm.tbl_scope_id = tbl_scope_id;
890
891                 /* set the table entry */
892                 rc = tf_set_tbl_entry(parms->tfp, &set_parm);
893                 if (rc) {
894                         BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n",
895                                     set_parm.type,
896                                     (set_parm.dir == TF_DIR_RX) ? "RX" : "TX",
897                                     set_parm.idx);
898                         goto error;
899                 }
900         }
901
902         /* Link the resource to the flow in the flow db */
903         memset(&fid_parms, 0, sizeof(fid_parms));
904         fid_parms.direction             = atbls->direction;
905         fid_parms.resource_func         = atbls->resource_func;
906         fid_parms.resource_type         = atbls->table_type;
907         fid_parms.resource_hndl         = alloc_parms.idx;
908         fid_parms.critical_resource     = 0;
909
910         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
911                                       parms->tbl_idx,
912                                       parms->fid,
913                                       &fid_parms);
914         if (rc) {
915                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
916                             rc);
917                 rc = -EINVAL;
918                 goto error;
919         }
920
921         return 0;
922 error:
923
924         free_parms.dir  = alloc_parms.dir;
925         free_parms.type = alloc_parms.type;
926         free_parms.idx  = alloc_parms.idx;
927
928         trc = tf_free_tbl_entry(parms->tfp, &free_parms);
929         if (trc)
930                 BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n");
931
932         return rc;
933 }
934
935 /*
936  * Function to process the action Info. Iterate through the list
937  * action info templates and process it.
938  */
939 static int32_t
940 ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms,
941                                struct bnxt_ulp_mapper_act_tbl_info *tbl)
942 {
943         struct ulp_blob                                 blob;
944         struct bnxt_ulp_mapper_result_field_info        *flds, *fld;
945         uint32_t                                        num_flds = 0;
946         uint32_t                                        encap_flds = 0;
947         uint32_t                                        i;
948         int32_t                                         rc;
949         uint16_t                                        bit_size;
950
951         if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile)
952                 return -EINVAL;
953
954         /* use the max size if encap is enabled */
955         if (tbl->encap_num_fields)
956                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
957         else
958                 bit_size = tbl->result_bit_size;
959         if (!ulp_blob_init(&blob, bit_size, parms->order)) {
960                 BNXT_TF_DBG(ERR, "action blob init failed\n");
961                 return -EINVAL;
962         }
963
964         flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds);
965         if (!flds || !num_flds) {
966                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
967                 return -EINVAL;
968         }
969
970         for (i = 0; i < (num_flds + encap_flds); i++) {
971                 fld = &flds[i];
972                 rc = ulp_mapper_result_field_process(parms,
973                                                      tbl->direction,
974                                                      fld,
975                                                      &blob,
976                                                      "Action");
977                 if (rc) {
978                         BNXT_TF_DBG(ERR, "Action field failed\n");
979                         return rc;
980                 }
981                 /* set the swap index if 64 bit swap is enabled */
982                 if (parms->encap_byte_swap && encap_flds) {
983                         if ((i + 1) == num_flds)
984                                 ulp_blob_encap_swap_idx_set(&blob);
985                         /* if 64 bit swap is enabled perform the 64bit swap */
986                         if ((i + 1) == (num_flds + encap_flds))
987                                 ulp_blob_perform_encap_swap(&blob);
988                 }
989         }
990
991         rc = ulp_mapper_action_alloc_and_set(parms, &blob);
992         return rc;
993 }
994
995 static int32_t
996 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
997                             struct bnxt_ulp_mapper_class_tbl_info *tbl)
998 {
999         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
1000         struct ulp_blob key, mask, data;
1001         uint32_t i, num_kflds;
1002         struct tf *tfp;
1003         int32_t rc, trc;
1004         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
1005         struct tf_set_tcam_entry_parms sparms           = { 0 };
1006         struct ulp_flow_db_res_params   fid_parms       = { 0 };
1007         struct tf_free_tcam_entry_parms free_parms      = { 0 };
1008         uint32_t hit = 0;
1009         uint16_t tmplen = 0;
1010
1011         /* Skip this if was handled by the cache. */
1012         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
1013                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1014                 return 0;
1015         }
1016
1017         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1018         if (!tfp) {
1019                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1020                 return -EINVAL;
1021         }
1022
1023         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1024         if (!kflds || !num_kflds) {
1025                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1026                 return -EINVAL;
1027         }
1028
1029         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) ||
1030             !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) ||
1031             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1032                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1033                 return -EINVAL;
1034         }
1035
1036         /* create the key/mask */
1037         /*
1038          * NOTE: The WC table will require some kind of flag to handle the
1039          * mode bits within the key/mask
1040          */
1041         for (i = 0; i < num_kflds; i++) {
1042                 /* Setup the key */
1043                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1044                                                       &kflds[i],
1045                                                       &key, 1, "TCAM Key");
1046                 if (rc) {
1047                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1048                         return rc;
1049                 }
1050
1051                 /* Setup the mask */
1052                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1053                                                       &kflds[i],
1054                                                       &mask, 0, "TCAM Mask");
1055                 if (rc) {
1056                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1057                         return rc;
1058                 }
1059         }
1060
1061         aparms.dir              = tbl->direction;
1062         aparms.tcam_tbl_type    = tbl->table_type;
1063         aparms.search_enable    = tbl->srch_b4_alloc;
1064         aparms.key_sz_in_bits   = tbl->key_bit_size;
1065         aparms.key              = ulp_blob_data_get(&key, &tmplen);
1066         if (tbl->key_bit_size != tmplen) {
1067                 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1068                             tmplen, tbl->key_bit_size);
1069                 return -EINVAL;
1070         }
1071
1072         aparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1073         if (tbl->key_bit_size != tmplen) {
1074                 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1075                             tmplen, tbl->key_bit_size);
1076                 return -EINVAL;
1077         }
1078
1079         aparms.priority         = tbl->priority;
1080
1081         /*
1082          * All failures after this succeeds require the entry to be freed.
1083          * cannot return directly on failure, but needs to goto error
1084          */
1085         rc = tf_alloc_tcam_entry(tfp, &aparms);
1086         if (rc) {
1087                 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1088                 return rc;
1089         }
1090
1091         hit = aparms.hit;
1092
1093         /* Build the result */
1094         if (!tbl->srch_b4_alloc || !hit) {
1095                 struct bnxt_ulp_mapper_result_field_info *dflds;
1096                 struct bnxt_ulp_mapper_ident_info *idents;
1097                 uint32_t num_dflds, num_idents;
1098
1099                 /*
1100                  * Since the cache entry is responsible for allocating
1101                  * identifiers when in use, allocate the identifiers only
1102                  * during normal processing.
1103                  */
1104                 if (parms->tcam_tbl_opc ==
1105                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1106                         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1107
1108                         for (i = 0; i < num_idents; i++) {
1109                                 rc = ulp_mapper_ident_process(parms, tbl,
1110                                                               &idents[i], NULL);
1111                                 /* Already logged the error, just return */
1112                                 if (rc)
1113                                         goto error;
1114                         }
1115                 }
1116
1117                 /* Create the result data blob */
1118                 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1119                 if (!dflds || !num_dflds) {
1120                         BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1121                         rc = -EINVAL;
1122                         goto error;
1123                 }
1124
1125                 for (i = 0; i < num_dflds; i++) {
1126                         rc = ulp_mapper_result_field_process(parms,
1127                                                              tbl->direction,
1128                                                              &dflds[i],
1129                                                              &data,
1130                                                              "TCAM Result");
1131                         if (rc) {
1132                                 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
1133                                 goto error;
1134                         }
1135                 }
1136
1137                 sparms.dir              = aparms.dir;
1138                 sparms.tcam_tbl_type    = aparms.tcam_tbl_type;
1139                 sparms.idx              = aparms.idx;
1140                 /* Already verified the key/mask lengths */
1141                 sparms.key              = ulp_blob_data_get(&key, &tmplen);
1142                 sparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1143                 sparms.key_sz_in_bits   = tbl->key_bit_size;
1144                 sparms.result           = ulp_blob_data_get(&data, &tmplen);
1145
1146                 if (tbl->result_bit_size != tmplen) {
1147                         BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1148                                     tmplen, tbl->result_bit_size);
1149                         rc = -EINVAL;
1150                         goto error;
1151                 }
1152                 sparms.result_sz_in_bits = tbl->result_bit_size;
1153
1154                 rc = tf_set_tcam_entry(tfp, &sparms);
1155                 if (rc) {
1156                         BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
1157                                     sparms.tcam_tbl_type,
1158                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1159                                     sparms.idx);
1160                         goto error;
1161                 }
1162
1163                 /* Update cache with TCAM index if the was cache allocated. */
1164                 if (parms->tcam_tbl_opc ==
1165                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) {
1166                         if (!parms->cache_ptr) {
1167                                 BNXT_TF_DBG(ERR, "Unable to update cache");
1168                                 rc = -EINVAL;
1169                                 goto error;
1170                         }
1171                         parms->cache_ptr->tcam_idx = aparms.idx;
1172                 }
1173
1174         } else {
1175                 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
1176                 rc = -EINVAL;
1177                 goto error;
1178         }
1179
1180         /*
1181          * Only link the entry to the flow db in the event that cache was not
1182          * used.
1183          */
1184         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1185                 fid_parms.direction = tbl->direction;
1186                 fid_parms.resource_func = tbl->resource_func;
1187                 fid_parms.resource_type = tbl->table_type;
1188                 fid_parms.critical_resource = tbl->critical_resource;
1189                 fid_parms.resource_hndl = aparms.idx;
1190                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1191                                               parms->tbl_idx,
1192                                               parms->fid,
1193                                               &fid_parms);
1194                 if (rc) {
1195                         BNXT_TF_DBG(ERR,
1196                                     "Failed to link resource to flow rc = %d\n",
1197                                     rc);
1198                         /* Need to free the identifier, so goto error */
1199                         goto error;
1200                 }
1201         } else {
1202                 /*
1203                  * Reset the tcam table opcode to normal in case the next tcam
1204                  * entry does not use cache.
1205                  */
1206                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1207                 parms->cache_ptr = NULL;
1208         }
1209
1210         return 0;
1211 error:
1212         parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1213         free_parms.dir                  = tbl->direction;
1214         free_parms.tcam_tbl_type        = tbl->table_type;
1215         free_parms.idx                  = aparms.idx;
1216         trc = tf_free_tcam_entry(tfp, &free_parms);
1217         if (trc)
1218                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1219                             tbl->table_type, tbl->direction, aparms.idx);
1220
1221         return rc;
1222 }
1223
1224 static int32_t
1225 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1226                           struct bnxt_ulp_mapper_class_tbl_info *tbl)
1227 {
1228         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
1229         struct bnxt_ulp_mapper_result_field_info *dflds;
1230         struct ulp_blob key, data;
1231         uint32_t i, num_kflds, num_dflds;
1232         uint16_t tmplen;
1233         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1234         struct ulp_rte_act_prop  *a_prop = parms->act_prop;
1235         struct ulp_flow_db_res_params   fid_parms = { 0 };
1236         struct tf_insert_em_entry_parms iparms = { 0 };
1237         struct tf_delete_em_entry_parms free_parms = { 0 };
1238         int32_t trc;
1239         int32_t rc = 0;
1240
1241         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1242         if (!kflds || !num_kflds) {
1243                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1244                 return -EINVAL;
1245         }
1246
1247         /* Initialize the key/result blobs */
1248         if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
1249             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1250                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1251                 return -EINVAL;
1252         }
1253
1254         /* create the key */
1255         for (i = 0; i < num_kflds; i++) {
1256                 /* Setup the key */
1257                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1258                                                       &kflds[i],
1259                                                       &key, 1, "EM Key");
1260                 if (rc) {
1261                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1262                         return rc;
1263                 }
1264         }
1265
1266         /*
1267          * TBD: Normally should process identifiers in case of using recycle or
1268          * loopback.  Not supporting recycle for now.
1269          */
1270
1271         /* Create the result data blob */
1272         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1273         if (!dflds || !num_dflds) {
1274                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1275                 return -EINVAL;
1276         }
1277
1278         for (i = 0; i < num_dflds; i++) {
1279                 struct bnxt_ulp_mapper_result_field_info *fld;
1280
1281                 fld = &dflds[i];
1282
1283                 rc = ulp_mapper_result_field_process(parms,
1284                                                      tbl->direction,
1285                                                      fld,
1286                                                      &data,
1287                                                      "EM Result");
1288                 if (rc) {
1289                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1290                         return rc;
1291                 }
1292         }
1293
1294         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1295                                              &iparms.tbl_scope_id);
1296         if (rc) {
1297                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1298                 return rc;
1299         }
1300
1301         /*
1302          * NOTE: the actual blob size will differ from the size in the tbl
1303          * entry due to the padding.
1304          */
1305         iparms.dup_check                = 0;
1306         iparms.dir                      = tbl->direction;
1307         iparms.mem                      = tbl->table_type;
1308         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1309         iparms.key_sz_in_bits           = tbl->key_bit_size;
1310         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1311         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1312
1313         rc = tf_insert_em_entry(tfp, &iparms);
1314         if (rc) {
1315                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1316                 return rc;
1317         }
1318
1319         if (tbl->mark_enable &&
1320             ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1321                              BNXT_ULP_ACTION_BIT_MARK)) {
1322                 uint32_t val, mark, gfid, flag;
1323                 /* TBD: Need to determine if GFID is enabled globally */
1324                 if (sizeof(val) != BNXT_ULP_ACT_PROP_SZ_MARK) {
1325                         BNXT_TF_DBG(ERR, "Mark size (%d) != expected (%zu)\n",
1326                                     BNXT_ULP_ACT_PROP_SZ_MARK, sizeof(val));
1327                         rc = -EINVAL;
1328                         goto error;
1329                 }
1330
1331                 memcpy(&val,
1332                        &a_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1333                        sizeof(val));
1334
1335                 mark = tfp_be_to_cpu_32(val);
1336
1337                 TF_GET_GFID_FROM_FLOW_ID(iparms.flow_id, gfid);
1338                 flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1339                 rc = ulp_mark_db_mark_add(parms->ulp_ctx,
1340                                           flag,
1341                                           gfid,
1342                                           mark);
1343                 if (rc) {
1344                         BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1345                         goto error;
1346                 }
1347
1348                 /*
1349                  * Link the mark resource to the flow in the flow db
1350                  * The mark is never the critical resource, so it is 0.
1351                  */
1352                 memset(&fid_parms, 0, sizeof(fid_parms));
1353                 fid_parms.direction     = tbl->direction;
1354                 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1355                 fid_parms.resource_type = flag;
1356                 fid_parms.resource_hndl = gfid;
1357                 fid_parms.critical_resource = 0;
1358
1359                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1360                                               parms->tbl_idx,
1361                                               parms->fid,
1362                                               &fid_parms);
1363                 if (rc) {
1364                         BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1365                                     rc);
1366                         /* Need to free the identifier, so goto error */
1367                         goto error;
1368                 }
1369         }
1370
1371         /* Link the EM resource to the flow in the flow db */
1372         memset(&fid_parms, 0, sizeof(fid_parms));
1373         fid_parms.direction             = tbl->direction;
1374         fid_parms.resource_func         = tbl->resource_func;
1375         fid_parms.resource_type         = tbl->table_type;
1376         fid_parms.critical_resource     = tbl->critical_resource;
1377         fid_parms.resource_hndl         = iparms.flow_handle;
1378
1379         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1380                                       parms->tbl_idx,
1381                                       parms->fid,
1382                                       &fid_parms);
1383         if (rc) {
1384                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1385                             rc);
1386                 /* Need to free the identifier, so goto error */
1387                 goto error;
1388         }
1389
1390         return 0;
1391 error:
1392         free_parms.dir          = iparms.dir;
1393         free_parms.mem          = iparms.mem;
1394         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1395         free_parms.flow_handle  = iparms.flow_handle;
1396
1397         trc = tf_delete_em_entry(tfp, &free_parms);
1398         if (trc)
1399                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1400
1401         return rc;
1402 }
1403
1404 static int32_t
1405 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1406                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1407 {
1408         struct bnxt_ulp_mapper_result_field_info *flds;
1409         struct ulp_flow_db_res_params   fid_parms;
1410         struct ulp_blob data;
1411         uint64_t idx;
1412         uint16_t tmplen;
1413         uint32_t i, num_flds;
1414         int32_t rc = 0, trc = 0;
1415         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1416         struct tf_set_tbl_entry_parms   sparms = { 0 };
1417         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1418         uint32_t tbl_scope_id;
1419         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1420
1421         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1422
1423         if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1424                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1425                 return -EINVAL;
1426         }
1427
1428         flds = ulp_mapper_result_fields_get(tbl, &num_flds);
1429         if (!flds || !num_flds) {
1430                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
1431                 return -EINVAL;
1432         }
1433
1434         for (i = 0; i < num_flds; i++) {
1435                 rc = ulp_mapper_result_field_process(parms,
1436                                                      tbl->direction,
1437                                                      &flds[i],
1438                                                      &data,
1439                                                      "Indexed Result");
1440                 if (rc) {
1441                         BNXT_TF_DBG(ERR, "data field failed\n");
1442                         return rc;
1443                 }
1444         }
1445
1446         aparms.dir              = tbl->direction;
1447         aparms.type             = tbl->table_type;
1448         aparms.search_enable    = tbl->srch_b4_alloc;
1449         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1450         aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1451         aparms.tbl_scope_id     = tbl_scope_id;
1452
1453         /* All failures after the alloc succeeds require a free */
1454         rc = tf_alloc_tbl_entry(tfp, &aparms);
1455         if (rc) {
1456                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1457                             tbl->table_type,
1458                             (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1459                             rc);
1460                 return rc;
1461         }
1462
1463         /* Always storing values in Regfile in BE */
1464         idx = tfp_cpu_to_be_64(aparms.idx);
1465         rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1466         if (!rc) {
1467                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1468                             tbl->regfile_wr_idx);
1469                 goto error;
1470         }
1471
1472         if (!tbl->srch_b4_alloc) {
1473                 sparms.dir              = tbl->direction;
1474                 sparms.type             = tbl->table_type;
1475                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1476                 sparms.data_sz_in_bytes =
1477                         ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1478                 sparms.idx              = aparms.idx;
1479                 sparms.tbl_scope_id     = tbl_scope_id;
1480
1481                 rc = tf_set_tbl_entry(tfp, &sparms);
1482                 if (rc) {
1483                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1484                                     tbl->table_type,
1485                                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1486                                     sparms.idx,
1487                                     rc);
1488
1489                         goto error;
1490                 }
1491         }
1492
1493         /* Link the resource to the flow in the flow db */
1494         memset(&fid_parms, 0, sizeof(fid_parms));
1495         fid_parms.direction     = tbl->direction;
1496         fid_parms.resource_func = tbl->resource_func;
1497         fid_parms.resource_type = tbl->table_type;
1498         fid_parms.resource_hndl = aparms.idx;
1499         fid_parms.critical_resource     = 0;
1500
1501         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1502                                       parms->tbl_idx,
1503                                       parms->fid,
1504                                       &fid_parms);
1505         if (rc) {
1506                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1507                             rc);
1508                 goto error;
1509         }
1510
1511         return rc;
1512 error:
1513         /*
1514          * Free the allocated resource since we failed to either
1515          * write to the entry or link the flow
1516          */
1517         free_parms.dir  = tbl->direction;
1518         free_parms.type = tbl->table_type;
1519         free_parms.idx  = aparms.idx;
1520         free_parms.tbl_scope_id = tbl_scope_id;
1521
1522         trc = tf_free_tbl_entry(tfp, &free_parms);
1523         if (trc)
1524                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1525
1526         return rc;
1527 }
1528
1529 static int32_t
1530 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1531                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1532 {
1533         struct bnxt_ulp_mapper_class_key_field_info *kflds;
1534         struct bnxt_ulp_mapper_cache_entry *cache_entry;
1535         struct bnxt_ulp_mapper_ident_info *idents;
1536         uint32_t i, num_kflds = 0, num_idents = 0;
1537         struct ulp_flow_db_res_params fid_parms;
1538         struct tf_free_identifier_parms fparms;
1539         uint16_t tmplen, tmp_ident;
1540         struct ulp_blob key;
1541         uint8_t *cache_key;
1542         uint64_t regval;
1543         uint16_t *ckey;
1544         int32_t rc;
1545
1546         /* Get the key fields list and build the key. */
1547         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1548         if (!kflds || !num_kflds) {
1549                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1550                 return -EINVAL;
1551         }
1552         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order)) {
1553                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
1554                 return -EINVAL;
1555         }
1556         for (i = 0; i < num_kflds; i++) {
1557                 /* Setup the key */
1558                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1559                                                       &kflds[i],
1560                                                       &key, 1, "Cache Key");
1561                 if (rc) {
1562                         BNXT_TF_DBG(ERR,
1563                                     "Failed to create key for Cache rc=%d\n",
1564                                     rc);
1565                         return -EINVAL;
1566                 }
1567         }
1568
1569         /*
1570          * Perform the lookup in the cache table with constructed key.  The
1571          * cache_key is a byte array of tmplen, it needs to be converted to a
1572          * index for the cache table.
1573          */
1574         cache_key = ulp_blob_data_get(&key, &tmplen);
1575         ckey = (uint16_t *)cache_key;
1576         cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
1577                                                  tbl->cache_tbl_id,
1578                                                  *ckey);
1579
1580         /*
1581          * Get the identifier list for processing by both the hit and miss
1582          * processing.
1583          */
1584         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1585
1586         if (!cache_entry->ref_count) {
1587                 /* Initialize the cache entry */
1588                 cache_entry->tcam_idx = 0;
1589                 cache_entry->ref_count = 0;
1590                 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
1591                         cache_entry->idents[i] = ULP_IDENTS_INVALID;
1592
1593                 /* Need to allocate identifiers for storing in the cache. */
1594                 for (i = 0; i < num_idents; i++) {
1595                         /*
1596                          * Since we are using the cache, the identifier does not
1597                          * get added to the flow db.  Pass in the pointer to the
1598                          * tmp_ident.
1599                          */
1600                         rc = ulp_mapper_ident_process(parms, tbl,
1601                                                       &idents[i], &tmp_ident);
1602                         if (rc)
1603                                 goto error;
1604
1605                         cache_entry->ident_types[i] = idents[i].ident_type;
1606                         cache_entry->idents[i] = tmp_ident;
1607                 }
1608
1609                 /* Tell the TCAM processor to alloc an entry */
1610                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
1611                 /* Store the cache key for use by the tcam process code */
1612                 parms->cache_ptr = cache_entry;
1613         } else {
1614                 /* Cache hit, get values from result. */
1615                 for (i = 0; i < num_idents; i++) {
1616                         regval = (uint64_t)cache_entry->idents[i];
1617                         if (!ulp_regfile_write(parms->regfile,
1618                                                idents[i].regfile_wr_idx,
1619                                                tfp_cpu_to_be_64(regval))) {
1620                                 BNXT_TF_DBG(ERR,
1621                                             "Failed to write to regfile\n");
1622                                 return -EINVAL;
1623                         }
1624                 }
1625                 /*
1626                  * The cached entry is being used, so let the tcam processing
1627                  * know not to process this table.
1628                  */
1629                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
1630         }
1631
1632         /* Made through the cache processing, increment the reference count. */
1633         cache_entry->ref_count++;
1634
1635         /* Link the cache to the flow db. */
1636         memset(&fid_parms, 0, sizeof(fid_parms));
1637         fid_parms.direction = tbl->direction;
1638         fid_parms.resource_func = tbl->resource_func;
1639
1640         /*
1641          * Cache resource type is composed of both table_type and cache_tbl_id
1642          * need to set it appropriately via setter.
1643          */
1644         ulp_mapper_cache_res_type_set(&fid_parms,
1645                                       tbl->table_type,
1646                                       tbl->cache_tbl_id);
1647         fid_parms.resource_hndl = (uint64_t)*ckey;
1648         fid_parms.critical_resource = tbl->critical_resource;
1649         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1650                                       parms->tbl_idx,
1651                                       parms->fid,
1652                                       &fid_parms);
1653         if (rc)
1654                 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
1655
1656         return rc;
1657 error:
1658         /*
1659          * This error handling only gets called when the idents are being
1660          * allocated for the cache on misses.  Using the num_idents that was
1661          * previously set.
1662          */
1663         for (i = 0; i < num_idents; i++) {
1664                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
1665                         continue;
1666
1667                 fparms.dir = tbl->direction;
1668                 fparms.ident_type = idents[i].ident_type;
1669                 fparms.id = cache_entry->idents[i];
1670                 tf_free_identifier(parms->tfp, &fparms);
1671         }
1672
1673         return rc;
1674 }
1675
1676 /*
1677  * Function to process the action template. Iterate through the list
1678  * action info templates and process it.
1679  */
1680 static int32_t
1681 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1682 {
1683         uint32_t        i;
1684         int32_t         rc = 0;
1685
1686         if (!parms->atbls || !parms->num_atbls) {
1687                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1688                             parms->dev_id, parms->act_tid);
1689                 return -EINVAL;
1690         }
1691
1692         for (i = 0; i < parms->num_atbls; i++) {
1693                 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1694                 if (rc)
1695                         return rc;
1696         }
1697
1698         return rc;
1699 }
1700
1701 /* Create the classifier table entries for a flow. */
1702 static int32_t
1703 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1704 {
1705         uint32_t        i;
1706         int32_t         rc = 0;
1707
1708         if (!parms)
1709                 return -EINVAL;
1710
1711         if (!parms->ctbls || !parms->num_ctbls) {
1712                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1713                             parms->dev_id, parms->class_tid);
1714                 return -EINVAL;
1715         }
1716
1717         for (i = 0; i < parms->num_ctbls; i++) {
1718                 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1719
1720                 switch (tbl->resource_func) {
1721                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1722                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1723                         break;
1724                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1725                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1726                         break;
1727                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1728                         rc = ulp_mapper_index_tbl_process(parms, tbl);
1729                         break;
1730                 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1731                         rc = ulp_mapper_cache_tbl_process(parms, tbl);
1732                         break;
1733                 default:
1734                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1735                                     tbl->resource_func);
1736                         return -EINVAL;
1737                 }
1738
1739                 if (rc) {
1740                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1741                                     tbl->resource_func);
1742                         return rc;
1743                 }
1744         }
1745
1746         return rc;
1747 }
1748
1749 static int32_t
1750 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1751                          struct ulp_flow_db_res_params *res)
1752 {
1753         struct tf *tfp;
1754         int32_t rc = 0;
1755
1756         if (!res || !ulp) {
1757                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1758                 return -EINVAL;
1759         }
1760
1761         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1762         if (!tfp) {
1763                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1764                 return -EINVAL;
1765         }
1766
1767         switch (res->resource_func) {
1768         case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1769                 rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
1770                 break;
1771         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1772                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1773                 break;
1774         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1775                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1776                 break;
1777         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1778                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1779                 break;
1780         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1781                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1782                 break;
1783         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1784                 rc = ulp_mapper_mark_free(ulp, res);
1785                 break;
1786         default:
1787                 break;
1788         }
1789
1790         return rc;
1791 }
1792
1793 int32_t
1794 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
1795                           uint32_t fid,
1796                           enum bnxt_ulp_flow_db_tables  tbl_type)
1797 {
1798         struct ulp_flow_db_res_params   res_parms = { 0 };
1799         int32_t                         rc, trc;
1800
1801         if (!ulp_ctx) {
1802                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1803                 return -EINVAL;
1804         }
1805
1806         /*
1807          * Set the critical resource on the first resource del, then iterate
1808          * while status is good
1809          */
1810         res_parms.critical_resource = 1;
1811         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
1812
1813         if (rc) {
1814                 /*
1815                  * This is unexpected on the first call to resource del.
1816                  * It likely means that the flow did not exist in the flow db.
1817                  */
1818                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
1819                             tbl_type, fid, rc);
1820                 return rc;
1821         }
1822
1823         while (!rc) {
1824                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
1825                 if (trc)
1826                         /*
1827                          * On fail, we still need to attempt to free the
1828                          * remaining resources.  Don't return
1829                          */
1830                         BNXT_TF_DBG(ERR,
1831                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
1832                                     "] failed rc=%d.\n",
1833                                     tbl_type, fid, res_parms.resource_func,
1834                                     res_parms.resource_hndl, trc);
1835
1836                 /* All subsequent call require the critical_resource be zero */
1837                 res_parms.critical_resource = 0;
1838
1839                 rc = ulp_flow_db_resource_del(ulp_ctx,
1840                                               tbl_type,
1841                                               fid,
1842                                               &res_parms);
1843         }
1844
1845         /* Free the Flow ID since we've removed all resources */
1846         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
1847
1848         return rc;
1849 }
1850
1851 int32_t
1852 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
1853 {
1854         if (!ulp_ctx) {
1855                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1856                 return -EINVAL;
1857         }
1858
1859         return ulp_mapper_resources_free(ulp_ctx,
1860                                          fid,
1861                                          BNXT_ULP_REGULAR_FLOW_TABLE);
1862 }
1863
1864 /* Function to handle the mapping of the Flow to be compatible
1865  * with the underlying hardware.
1866  */
1867 int32_t
1868 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
1869                        struct bnxt_ulp_mapper_create_parms *cparms,
1870                        uint32_t *flowid)
1871 {
1872         struct bnxt_ulp_device_params *device_params;
1873         struct bnxt_ulp_mapper_parms parms;
1874         struct ulp_regfile regfile;
1875         int32_t  rc, trc;
1876
1877         if (!ulp_ctx || !cparms)
1878                 return -EINVAL;
1879
1880         /* Initialize the parms structure */
1881         memset(&parms, 0, sizeof(parms));
1882         parms.act_prop = cparms->act_prop;
1883         parms.act_bitmap = cparms->act;
1884         parms.regfile = &regfile;
1885         parms.hdr_field = cparms->hdr_field;
1886         parms.comp_fld = cparms->comp_fld;
1887         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1888         parms.ulp_ctx = ulp_ctx;
1889         parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1890
1891         /* Get the device id from the ulp context */
1892         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
1893                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
1894                 return -EINVAL;
1895         }
1896
1897         /*
1898          * Get the mapper data for dynamic mapper data such as default
1899          * ids.
1900          */
1901         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
1902                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
1903         if (!parms.mapper_data) {
1904                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
1905                 return -EINVAL;
1906         }
1907
1908         /* Get the action table entry from device id and act context id */
1909         parms.act_tid = cparms->act_tid;
1910         parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
1911                                                      parms.act_tid,
1912                                                      &parms.num_atbls);
1913         if (!parms.atbls || !parms.num_atbls) {
1914                 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
1915                             parms.dev_id, parms.act_tid);
1916                 return -EINVAL;
1917         }
1918
1919         /* Get the class table entry from device id and act context id */
1920         parms.class_tid = cparms->class_tid;
1921         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
1922                                                     parms.class_tid,
1923                                                     &parms.num_ctbls);
1924         if (!parms.ctbls || !parms.num_ctbls) {
1925                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1926                             parms.dev_id, parms.class_tid);
1927                 return -EINVAL;
1928         }
1929
1930         /* Get the byte order for the further processing from device params */
1931         device_params = bnxt_ulp_device_params_get(parms.dev_id);
1932         if (!device_params) {
1933                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1934                             parms.dev_id, parms.class_tid);
1935                 return -EINVAL;
1936         }
1937         parms.order = device_params->byte_order;
1938         parms.encap_byte_swap = device_params->encap_byte_swap;
1939
1940         /* initialize the registry file for further processing */
1941         if (!ulp_regfile_init(parms.regfile)) {
1942                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
1943                 return -EINVAL;
1944         }
1945
1946         rc = ulp_regfile_write(parms.regfile,
1947                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
1948                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
1949         if (!rc) {
1950                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
1951                 return -EINVAL;
1952         }
1953
1954         /* Allocate a Flow ID for attaching all resources for the flow to.
1955          * Once allocated, all errors have to walk the list of resources and
1956          * free each of them.
1957          */
1958         rc = ulp_flow_db_fid_alloc(ulp_ctx,
1959                                    BNXT_ULP_REGULAR_FLOW_TABLE,
1960                                    cparms->func_id,
1961                                    &parms.fid);
1962         if (rc) {
1963                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
1964                 return rc;
1965         }
1966
1967         /* Process the action template list from the selected action table*/
1968         rc = ulp_mapper_action_tbls_process(&parms);
1969         if (rc) {
1970                 BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n",
1971                             parms.dev_id, parms.act_tid);
1972                 goto flow_error;
1973         }
1974
1975         /* All good. Now process the class template */
1976         rc = ulp_mapper_class_tbls_process(&parms);
1977         if (rc) {
1978                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
1979                             parms.dev_id, parms.class_tid);
1980                 goto flow_error;
1981         }
1982
1983         *flowid = parms.fid;
1984
1985         return rc;
1986
1987 flow_error:
1988         /* Free all resources that were allocated during flow creation */
1989         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
1990         if (trc)
1991                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
1992
1993         return rc;
1994 }
1995
1996 int32_t
1997 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
1998 {
1999         struct bnxt_ulp_cache_tbl_params *tbl;
2000         struct tf_alloc_identifier_parms iparms;
2001         struct bnxt_ulp_mapper_data *data;
2002         struct bnxt_ulp_def_ident_info *dflt_ids;
2003         uint32_t i, num_dflt_ids, reg_idx;
2004         uint64_t regval;
2005         struct tf *tfp;
2006         int32_t rc, csize;
2007
2008         if (!ulp_ctx)
2009                 return -EINVAL;
2010
2011         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2012         if (!tfp)
2013                 return -EINVAL;
2014
2015         data = rte_zmalloc("ulp_mapper_data",
2016                            sizeof(struct bnxt_ulp_mapper_data), 0);
2017         if (!data) {
2018                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2019                 return -ENOMEM;
2020         }
2021
2022         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2023                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2024                 /* Don't call deinit since the prof_func wasn't allocated. */
2025                 rte_free(data);
2026                 return -ENOMEM;
2027         }
2028
2029         /* Allocate the default ids. */
2030         dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids);
2031         for (i = 0; i < num_dflt_ids; i++) {
2032                 iparms.ident_type = dflt_ids[i].ident_type;
2033                 iparms.dir = dflt_ids[i].direction;
2034
2035                 rc = tf_alloc_identifier(tfp, &iparms);
2036                 if (rc) {
2037                         BNXT_TF_DBG(ERR, "Failed to alloc dflt "
2038                                     "identifier [%s][%d]\n",
2039                                     (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
2040                                     iparms.ident_type);
2041                         goto error;
2042                 }
2043                 reg_idx = dflt_ids[i].def_regfile_index;
2044                 /* All regfile entries are stored as 64bit big-endian values. */
2045                 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
2046                 rc = ulp_mapper_def_regfile_write(data, iparms.dir,
2047                                                  reg_idx, regval);
2048                 if (rc) {
2049                         BNXT_TF_DBG(ERR, "Failed to write to default "
2050                                     "regfile.\n");
2051                         goto error;
2052                 }
2053         }
2054
2055         /* Allocate the ulp cache tables. */
2056         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2057                 tbl = ulp_mapper_cache_tbl_params_get(i);
2058                 if (!tbl) {
2059                         BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2060                                     i);
2061                         goto error;
2062                 }
2063                 if (tbl->num_entries != 0) {
2064                         csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2065                                 tbl->num_entries;
2066                         data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2067                                                          csize, 0);
2068                         if (!data->cache_tbl[i]) {
2069                                 BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2070                                             "table %d.\n", i);
2071                                 rc = -ENOMEM;
2072                                 goto error;
2073                         }
2074                 }
2075         }
2076
2077         return 0;
2078 error:
2079         /* Ignore the return code in favor of returning the original error. */
2080         ulp_mapper_deinit(ulp_ctx);
2081         return rc;
2082 }
2083
2084 void
2085 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2086 {
2087         struct tf_free_identifier_parms free_parms;
2088         struct bnxt_ulp_def_ident_info *dflt_ids;
2089         struct bnxt_ulp_mapper_data *data;
2090         uint32_t i, num_dflt_ids, reg_idx;
2091         enum tf_dir dir;
2092         uint64_t regval;
2093         struct tf *tfp;
2094
2095         if (!ulp_ctx) {
2096                 BNXT_TF_DBG(ERR,
2097                             "Failed to acquire ulp context, so data may "
2098                             "not be released.\n");
2099                 return;
2100         }
2101
2102         data = (struct bnxt_ulp_mapper_data *)
2103                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2104         if (!data) {
2105                 /* Go ahead and return since there is no allocated data. */
2106                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2107                 return;
2108         }
2109
2110         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2111         if (!tfp) {
2112                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2113                 /* Free the mapper data regardless of errors. */
2114                 goto free_mapper_data;
2115         }
2116
2117         /* Free the default prof func ids per direction. */
2118         dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids);
2119         for (i = 0; i < num_dflt_ids; i++) {
2120                 reg_idx = dflt_ids[i].def_regfile_index;
2121                 dir = dflt_ids[i].direction;
2122                 free_parms.ident_type = dflt_ids[i].ident_type;
2123                 free_parms.dir = dir;
2124                 if (ulp_mapper_def_regfile_read(data, dir, reg_idx, &regval)) {
2125                         BNXT_TF_DBG(ERR, "Failed to read def regfile to free "
2126                                     "identifier.\n");
2127                         continue;
2128                 }
2129                 /*
2130                  * All regfile entries are stored as 64bit big-endian.  Need
2131                  * to convert the value to cpu before calling tf.
2132                  */
2133                 regval = tfp_be_to_cpu_64(regval);
2134                 free_parms.id = (uint16_t)regval;
2135                 /* Ignore errors and free the remaining identifiers. */
2136                 tf_free_identifier(tfp, &free_parms);
2137         }
2138
2139 free_mapper_data:
2140         /* Free the ulp cache tables */
2141         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2142                 rte_free(data->cache_tbl[i]);
2143                 data->cache_tbl[i] = NULL;
2144         }
2145
2146         rte_free(data);
2147         /* Reset the data pointer within the ulp_ctx. */
2148         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
2149 }