net/bnxt: support more resource functions in flow database
[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         default:
666                 return -EINVAL;
667         }
668         return 0;
669 }
670
671 /* Function to alloc action record and set the table. */
672 static int32_t
673 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
674                                  enum tf_dir dir,
675                                  struct bnxt_ulp_mapper_class_key_field_info *f,
676                                  struct ulp_blob *blob,
677                                  uint8_t is_key,
678                                  const char *name)
679 {
680         uint64_t val64;
681         uint16_t idx, bitlen;
682         uint32_t opcode;
683         uint8_t *operand;
684         struct ulp_regfile *regfile = parms->regfile;
685         uint8_t *val = NULL;
686         struct bnxt_ulp_mapper_class_key_field_info *fld = f;
687         uint32_t field_size;
688
689         if (is_key) {
690                 operand = fld->spec_operand;
691                 opcode  = fld->spec_opcode;
692         } else {
693                 operand = fld->mask_operand;
694                 opcode  = fld->mask_opcode;
695         }
696
697         bitlen = fld->field_bit_size;
698
699         switch (opcode) {
700         case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT:
701                 val = operand;
702                 if (!ulp_blob_push(blob, val, bitlen)) {
703                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
704                         return -EINVAL;
705                 }
706                 break;
707         case BNXT_ULP_SPEC_OPC_ADD_PAD:
708                 if (!ulp_blob_pad_push(blob, bitlen)) {
709                         BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
710                         return -EINVAL;
711                 }
712
713                 break;
714         case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD:
715                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
716                                       sizeof(uint16_t))) {
717                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
718                         return -EINVAL;
719                 }
720                 idx = tfp_be_to_cpu_16(idx);
721                 if (is_key)
722                         val = parms->hdr_field[idx].spec;
723                 else
724                         val = parms->hdr_field[idx].mask;
725
726                 /*
727                  * Need to account for how much data was pushed to the header
728                  * field vs how much is to be inserted in the key/mask.
729                  */
730                 field_size = parms->hdr_field[idx].size;
731                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
732                         field_size  = field_size - ((bitlen + 7) / 8);
733                         val += field_size;
734                 }
735
736                 if (!ulp_blob_push(blob, val, bitlen)) {
737                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
738                         return -EINVAL;
739                 }
740                 break;
741         case BNXT_ULP_SPEC_OPC_SET_TO_COMP_HDR_FIELD:
742                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
743                                       sizeof(uint16_t))) {
744                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
745                         return -EINVAL;
746                 }
747                 idx = tfp_be_to_cpu_16(idx);
748                 if (idx < BNXT_ULP_CHF_IDX_LAST)
749                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
750                                                bitlen);
751                 if (!val) {
752                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
753                         return -EINVAL;
754                 }
755                 break;
756         case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE:
757                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
758                                       sizeof(uint16_t))) {
759                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
760                         return -EINVAL;
761                 }
762                 idx = tfp_be_to_cpu_16(idx);
763
764                 if (!ulp_regfile_read(regfile, idx, &val64)) {
765                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
766                                     name, idx);
767                         return -EINVAL;
768                 }
769
770                 val = ulp_blob_push_64(blob, &val64, bitlen);
771                 if (!val) {
772                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
773                         return -EINVAL;
774                 }
775                 break;
776         case BNXT_ULP_SPEC_OPC_SET_TO_DEF_REGFILE:
777                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
778                                       sizeof(uint16_t))) {
779                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
780                         return -EINVAL;
781                 }
782                 idx = tfp_be_to_cpu_16(idx);
783                 if (ulp_mapper_def_regfile_read(parms->mapper_data,
784                                                 dir,
785                                                 idx, &val64)) {
786                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
787                                     name, idx);
788                         return -EINVAL;
789                 }
790                 val = ulp_blob_push_64(blob, &val64, bitlen);
791                 if (!val) {
792                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
793                         return -EINVAL;
794                 }
795                 break;
796         default:
797                 break;
798         }
799
800         return 0;
801 }
802
803 /* Function to alloc action record and set the table. */
804 static int32_t
805 ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms,
806                                 struct ulp_blob *blob)
807 {
808         struct ulp_flow_db_res_params           fid_parms;
809         struct tf_alloc_tbl_entry_parms         alloc_parms = { 0 };
810         struct tf_free_tbl_entry_parms          free_parms = { 0 };
811         struct bnxt_ulp_mapper_act_tbl_info     *atbls = parms->atbls;
812         int32_t                                 rc = 0;
813         int32_t trc;
814         uint64_t                                idx;
815         uint32_t tbl_scope_id;
816
817         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
818
819         /* Set the allocation parameters for the table*/
820         alloc_parms.dir = atbls->direction;
821         alloc_parms.type = atbls->table_type;
822         alloc_parms.search_enable = atbls->srch_b4_alloc;
823         alloc_parms.result = ulp_blob_data_get(blob,
824                                                &alloc_parms.result_sz_in_bytes);
825         alloc_parms.tbl_scope_id = tbl_scope_id;
826         if (!alloc_parms.result) {
827                 BNXT_TF_DBG(ERR, "blob is not populated\n");
828                 return -EINVAL;
829         }
830
831         rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms);
832         if (rc) {
833                 BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n",
834                             alloc_parms.type,
835                             (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX");
836                 return rc;
837         }
838
839         /* Need to calculate the idx for the result record */
840         uint64_t tmpidx = alloc_parms.idx;
841
842         if (atbls->table_type == TF_TBL_TYPE_EXT)
843                 tmpidx = TF_ACT_REC_OFFSET_2_PTR(alloc_parms.idx);
844         else
845                 tmpidx = alloc_parms.idx;
846
847         idx = tfp_cpu_to_be_64(tmpidx);
848
849         /* Store the allocated index for future use in the regfile */
850         rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx);
851         if (!rc) {
852                 BNXT_TF_DBG(ERR, "regfile[%d] write failed\n",
853                             atbls->regfile_wr_idx);
854                 rc = -EINVAL;
855                 goto error;
856         }
857
858         /*
859          * The set_tbl_entry API if search is not enabled or searched entry
860          * is not found.
861          */
862         if (!atbls->srch_b4_alloc || !alloc_parms.hit) {
863                 struct tf_set_tbl_entry_parms set_parm = { 0 };
864                 uint16_t        length;
865
866                 set_parm.dir    = atbls->direction;
867                 set_parm.type   = atbls->table_type;
868                 set_parm.idx    = alloc_parms.idx;
869                 set_parm.data   = ulp_blob_data_get(blob, &length);
870                 set_parm.data_sz_in_bytes = length / 8;
871
872                 if (set_parm.type == TF_TBL_TYPE_EXT)
873                         set_parm.tbl_scope_id = tbl_scope_id;
874
875                 /* set the table entry */
876                 rc = tf_set_tbl_entry(parms->tfp, &set_parm);
877                 if (rc) {
878                         BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n",
879                                     set_parm.type,
880                                     (set_parm.dir == TF_DIR_RX) ? "RX" : "TX",
881                                     set_parm.idx);
882                         goto error;
883                 }
884         }
885
886         /* Link the resource to the flow in the flow db */
887         memset(&fid_parms, 0, sizeof(fid_parms));
888         fid_parms.direction             = atbls->direction;
889         fid_parms.resource_func         = atbls->resource_func;
890         fid_parms.resource_type         = atbls->table_type;
891         fid_parms.resource_hndl         = alloc_parms.idx;
892         fid_parms.critical_resource     = 0;
893
894         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
895                                       parms->tbl_idx,
896                                       parms->fid,
897                                       &fid_parms);
898         if (rc) {
899                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
900                             rc);
901                 rc = -EINVAL;
902                 goto error;
903         }
904
905         return 0;
906 error:
907
908         free_parms.dir  = alloc_parms.dir;
909         free_parms.type = alloc_parms.type;
910         free_parms.idx  = alloc_parms.idx;
911
912         trc = tf_free_tbl_entry(parms->tfp, &free_parms);
913         if (trc)
914                 BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n");
915
916         return rc;
917 }
918
919 /*
920  * Function to process the action Info. Iterate through the list
921  * action info templates and process it.
922  */
923 static int32_t
924 ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms,
925                                struct bnxt_ulp_mapper_act_tbl_info *tbl)
926 {
927         struct ulp_blob                                 blob;
928         struct bnxt_ulp_mapper_result_field_info        *flds, *fld;
929         uint32_t                                        num_flds = 0;
930         uint32_t                                        encap_flds = 0;
931         uint32_t                                        i;
932         int32_t                                         rc;
933         uint16_t                                        bit_size;
934
935         if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile)
936                 return -EINVAL;
937
938         /* use the max size if encap is enabled */
939         if (tbl->encap_num_fields)
940                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
941         else
942                 bit_size = tbl->result_bit_size;
943         if (!ulp_blob_init(&blob, bit_size, parms->order)) {
944                 BNXT_TF_DBG(ERR, "action blob init failed\n");
945                 return -EINVAL;
946         }
947
948         flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds);
949         if (!flds || !num_flds) {
950                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
951                 return -EINVAL;
952         }
953
954         for (i = 0; i < (num_flds + encap_flds); i++) {
955                 fld = &flds[i];
956                 rc = ulp_mapper_result_field_process(parms,
957                                                      tbl->direction,
958                                                      fld,
959                                                      &blob,
960                                                      "Action");
961                 if (rc) {
962                         BNXT_TF_DBG(ERR, "Action field failed\n");
963                         return rc;
964                 }
965                 /* set the swap index if 64 bit swap is enabled */
966                 if (parms->encap_byte_swap && encap_flds) {
967                         if ((i + 1) == num_flds)
968                                 ulp_blob_encap_swap_idx_set(&blob);
969                         /* if 64 bit swap is enabled perform the 64bit swap */
970                         if ((i + 1) == (num_flds + encap_flds))
971                                 ulp_blob_perform_encap_swap(&blob);
972                 }
973         }
974
975         rc = ulp_mapper_action_alloc_and_set(parms, &blob);
976         return rc;
977 }
978
979 static int32_t
980 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
981                             struct bnxt_ulp_mapper_class_tbl_info *tbl)
982 {
983         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
984         struct ulp_blob key, mask, data;
985         uint32_t i, num_kflds;
986         struct tf *tfp;
987         int32_t rc, trc;
988         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
989         struct tf_set_tcam_entry_parms sparms           = { 0 };
990         struct ulp_flow_db_res_params   fid_parms       = { 0 };
991         struct tf_free_tcam_entry_parms free_parms      = { 0 };
992         uint32_t hit = 0;
993         uint16_t tmplen = 0;
994
995         /* Skip this if was handled by the cache. */
996         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
997                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
998                 return 0;
999         }
1000
1001         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1002         if (!tfp) {
1003                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1004                 return -EINVAL;
1005         }
1006
1007         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1008         if (!kflds || !num_kflds) {
1009                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1010                 return -EINVAL;
1011         }
1012
1013         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) ||
1014             !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) ||
1015             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1016                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1017                 return -EINVAL;
1018         }
1019
1020         /* create the key/mask */
1021         /*
1022          * NOTE: The WC table will require some kind of flag to handle the
1023          * mode bits within the key/mask
1024          */
1025         for (i = 0; i < num_kflds; i++) {
1026                 /* Setup the key */
1027                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1028                                                       &kflds[i],
1029                                                       &key, 1, "TCAM Key");
1030                 if (rc) {
1031                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1032                         return rc;
1033                 }
1034
1035                 /* Setup the mask */
1036                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1037                                                       &kflds[i],
1038                                                       &mask, 0, "TCAM Mask");
1039                 if (rc) {
1040                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1041                         return rc;
1042                 }
1043         }
1044
1045         aparms.dir              = tbl->direction;
1046         aparms.tcam_tbl_type    = tbl->table_type;
1047         aparms.search_enable    = tbl->srch_b4_alloc;
1048         aparms.key_sz_in_bits   = tbl->key_bit_size;
1049         aparms.key              = ulp_blob_data_get(&key, &tmplen);
1050         if (tbl->key_bit_size != tmplen) {
1051                 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1052                             tmplen, tbl->key_bit_size);
1053                 return -EINVAL;
1054         }
1055
1056         aparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1057         if (tbl->key_bit_size != tmplen) {
1058                 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1059                             tmplen, tbl->key_bit_size);
1060                 return -EINVAL;
1061         }
1062
1063         aparms.priority         = tbl->priority;
1064
1065         /*
1066          * All failures after this succeeds require the entry to be freed.
1067          * cannot return directly on failure, but needs to goto error
1068          */
1069         rc = tf_alloc_tcam_entry(tfp, &aparms);
1070         if (rc) {
1071                 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1072                 return rc;
1073         }
1074
1075         hit = aparms.hit;
1076
1077         /* Build the result */
1078         if (!tbl->srch_b4_alloc || !hit) {
1079                 struct bnxt_ulp_mapper_result_field_info *dflds;
1080                 struct bnxt_ulp_mapper_ident_info *idents;
1081                 uint32_t num_dflds, num_idents;
1082
1083                 /*
1084                  * Since the cache entry is responsible for allocating
1085                  * identifiers when in use, allocate the identifiers only
1086                  * during normal processing.
1087                  */
1088                 if (parms->tcam_tbl_opc ==
1089                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1090                         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1091
1092                         for (i = 0; i < num_idents; i++) {
1093                                 rc = ulp_mapper_ident_process(parms, tbl,
1094                                                               &idents[i], NULL);
1095                                 /* Already logged the error, just return */
1096                                 if (rc)
1097                                         goto error;
1098                         }
1099                 }
1100
1101                 /* Create the result data blob */
1102                 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1103                 if (!dflds || !num_dflds) {
1104                         BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1105                         rc = -EINVAL;
1106                         goto error;
1107                 }
1108
1109                 for (i = 0; i < num_dflds; i++) {
1110                         rc = ulp_mapper_result_field_process(parms,
1111                                                              tbl->direction,
1112                                                              &dflds[i],
1113                                                              &data,
1114                                                              "TCAM Result");
1115                         if (rc) {
1116                                 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
1117                                 goto error;
1118                         }
1119                 }
1120
1121                 sparms.dir              = aparms.dir;
1122                 sparms.tcam_tbl_type    = aparms.tcam_tbl_type;
1123                 sparms.idx              = aparms.idx;
1124                 /* Already verified the key/mask lengths */
1125                 sparms.key              = ulp_blob_data_get(&key, &tmplen);
1126                 sparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1127                 sparms.key_sz_in_bits   = tbl->key_bit_size;
1128                 sparms.result           = ulp_blob_data_get(&data, &tmplen);
1129
1130                 if (tbl->result_bit_size != tmplen) {
1131                         BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1132                                     tmplen, tbl->result_bit_size);
1133                         rc = -EINVAL;
1134                         goto error;
1135                 }
1136                 sparms.result_sz_in_bits = tbl->result_bit_size;
1137
1138                 rc = tf_set_tcam_entry(tfp, &sparms);
1139                 if (rc) {
1140                         BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
1141                                     sparms.tcam_tbl_type,
1142                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1143                                     sparms.idx);
1144                         goto error;
1145                 }
1146
1147                 /* Update cache with TCAM index if the was cache allocated. */
1148                 if (parms->tcam_tbl_opc ==
1149                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) {
1150                         if (!parms->cache_ptr) {
1151                                 BNXT_TF_DBG(ERR, "Unable to update cache");
1152                                 rc = -EINVAL;
1153                                 goto error;
1154                         }
1155                         parms->cache_ptr->tcam_idx = aparms.idx;
1156                 }
1157
1158         } else {
1159                 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
1160                 rc = -EINVAL;
1161                 goto error;
1162         }
1163
1164         /*
1165          * Only link the entry to the flow db in the event that cache was not
1166          * used.
1167          */
1168         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1169                 fid_parms.direction = tbl->direction;
1170                 fid_parms.resource_func = tbl->resource_func;
1171                 fid_parms.resource_type = tbl->table_type;
1172                 fid_parms.critical_resource = tbl->critical_resource;
1173                 fid_parms.resource_hndl = aparms.idx;
1174                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1175                                               parms->tbl_idx,
1176                                               parms->fid,
1177                                               &fid_parms);
1178                 if (rc) {
1179                         BNXT_TF_DBG(ERR,
1180                                     "Failed to link resource to flow rc = %d\n",
1181                                     rc);
1182                         /* Need to free the identifier, so goto error */
1183                         goto error;
1184                 }
1185         } else {
1186                 /*
1187                  * Reset the tcam table opcode to normal in case the next tcam
1188                  * entry does not use cache.
1189                  */
1190                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1191                 parms->cache_ptr = NULL;
1192         }
1193
1194         return 0;
1195 error:
1196         parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1197         free_parms.dir                  = tbl->direction;
1198         free_parms.tcam_tbl_type        = tbl->table_type;
1199         free_parms.idx                  = aparms.idx;
1200         trc = tf_free_tcam_entry(tfp, &free_parms);
1201         if (trc)
1202                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1203                             tbl->table_type, tbl->direction, aparms.idx);
1204
1205         return rc;
1206 }
1207
1208 static int32_t
1209 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1210                           struct bnxt_ulp_mapper_class_tbl_info *tbl)
1211 {
1212         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
1213         struct bnxt_ulp_mapper_result_field_info *dflds;
1214         struct ulp_blob key, data;
1215         uint32_t i, num_kflds, num_dflds;
1216         uint16_t tmplen;
1217         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1218         struct ulp_rte_act_prop  *a_prop = parms->act_prop;
1219         struct ulp_flow_db_res_params   fid_parms = { 0 };
1220         struct tf_insert_em_entry_parms iparms = { 0 };
1221         struct tf_delete_em_entry_parms free_parms = { 0 };
1222         int32_t trc;
1223         int32_t rc = 0;
1224
1225         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1226         if (!kflds || !num_kflds) {
1227                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1228                 return -EINVAL;
1229         }
1230
1231         /* Initialize the key/result blobs */
1232         if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
1233             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1234                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1235                 return -EINVAL;
1236         }
1237
1238         /* create the key */
1239         for (i = 0; i < num_kflds; i++) {
1240                 /* Setup the key */
1241                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1242                                                       &kflds[i],
1243                                                       &key, 1, "EM Key");
1244                 if (rc) {
1245                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1246                         return rc;
1247                 }
1248         }
1249
1250         /*
1251          * TBD: Normally should process identifiers in case of using recycle or
1252          * loopback.  Not supporting recycle for now.
1253          */
1254
1255         /* Create the result data blob */
1256         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1257         if (!dflds || !num_dflds) {
1258                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1259                 return -EINVAL;
1260         }
1261
1262         for (i = 0; i < num_dflds; i++) {
1263                 struct bnxt_ulp_mapper_result_field_info *fld;
1264
1265                 fld = &dflds[i];
1266
1267                 rc = ulp_mapper_result_field_process(parms,
1268                                                      tbl->direction,
1269                                                      fld,
1270                                                      &data,
1271                                                      "EM Result");
1272                 if (rc) {
1273                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1274                         return rc;
1275                 }
1276         }
1277
1278         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1279                                              &iparms.tbl_scope_id);
1280         if (rc) {
1281                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1282                 return rc;
1283         }
1284
1285         /*
1286          * NOTE: the actual blob size will differ from the size in the tbl
1287          * entry due to the padding.
1288          */
1289         iparms.dup_check                = 0;
1290         iparms.dir                      = tbl->direction;
1291         iparms.mem                      = tbl->table_type;
1292         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1293         iparms.key_sz_in_bits           = tbl->key_bit_size;
1294         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1295         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1296
1297         rc = tf_insert_em_entry(tfp, &iparms);
1298         if (rc) {
1299                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1300                 return rc;
1301         }
1302
1303         if (tbl->mark_enable &&
1304             ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1305                              BNXT_ULP_ACTION_BIT_MARK)) {
1306                 uint32_t val, mark, gfid, flag;
1307                 /* TBD: Need to determine if GFID is enabled globally */
1308                 if (sizeof(val) != BNXT_ULP_ACT_PROP_SZ_MARK) {
1309                         BNXT_TF_DBG(ERR, "Mark size (%d) != expected (%zu)\n",
1310                                     BNXT_ULP_ACT_PROP_SZ_MARK, sizeof(val));
1311                         rc = -EINVAL;
1312                         goto error;
1313                 }
1314
1315                 memcpy(&val,
1316                        &a_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1317                        sizeof(val));
1318
1319                 mark = tfp_be_to_cpu_32(val);
1320
1321                 TF_GET_GFID_FROM_FLOW_ID(iparms.flow_id, gfid);
1322                 flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1323                 rc = ulp_mark_db_mark_add(parms->ulp_ctx,
1324                                           flag,
1325                                           gfid,
1326                                           mark);
1327                 if (rc) {
1328                         BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1329                         goto error;
1330                 }
1331
1332                 /*
1333                  * Link the mark resource to the flow in the flow db
1334                  * The mark is never the critical resource, so it is 0.
1335                  */
1336                 memset(&fid_parms, 0, sizeof(fid_parms));
1337                 fid_parms.direction     = tbl->direction;
1338                 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1339                 fid_parms.resource_type = flag;
1340                 fid_parms.resource_hndl = gfid;
1341                 fid_parms.critical_resource = 0;
1342
1343                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1344                                               parms->tbl_idx,
1345                                               parms->fid,
1346                                               &fid_parms);
1347                 if (rc) {
1348                         BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1349                                     rc);
1350                         /* Need to free the identifier, so goto error */
1351                         goto error;
1352                 }
1353         }
1354
1355         /* Link the EM resource to the flow in the flow db */
1356         memset(&fid_parms, 0, sizeof(fid_parms));
1357         fid_parms.direction             = tbl->direction;
1358         fid_parms.resource_func         = tbl->resource_func;
1359         fid_parms.resource_type         = tbl->table_type;
1360         fid_parms.critical_resource     = tbl->critical_resource;
1361         fid_parms.resource_hndl         = iparms.flow_handle;
1362
1363         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1364                                       parms->tbl_idx,
1365                                       parms->fid,
1366                                       &fid_parms);
1367         if (rc) {
1368                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1369                             rc);
1370                 /* Need to free the identifier, so goto error */
1371                 goto error;
1372         }
1373
1374         return 0;
1375 error:
1376         free_parms.dir          = iparms.dir;
1377         free_parms.mem          = iparms.mem;
1378         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1379         free_parms.flow_handle  = iparms.flow_handle;
1380
1381         trc = tf_delete_em_entry(tfp, &free_parms);
1382         if (trc)
1383                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1384
1385         return rc;
1386 }
1387
1388 static int32_t
1389 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1390                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1391 {
1392         struct bnxt_ulp_mapper_result_field_info *flds;
1393         struct ulp_flow_db_res_params   fid_parms;
1394         struct ulp_blob data;
1395         uint64_t idx;
1396         uint16_t tmplen;
1397         uint32_t i, num_flds;
1398         int32_t rc = 0, trc = 0;
1399         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1400         struct tf_set_tbl_entry_parms   sparms = { 0 };
1401         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1402         uint32_t tbl_scope_id;
1403         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1404
1405         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1406
1407         if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1408                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1409                 return -EINVAL;
1410         }
1411
1412         flds = ulp_mapper_result_fields_get(tbl, &num_flds);
1413         if (!flds || !num_flds) {
1414                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
1415                 return -EINVAL;
1416         }
1417
1418         for (i = 0; i < num_flds; i++) {
1419                 rc = ulp_mapper_result_field_process(parms,
1420                                                      tbl->direction,
1421                                                      &flds[i],
1422                                                      &data,
1423                                                      "Indexed Result");
1424                 if (rc) {
1425                         BNXT_TF_DBG(ERR, "data field failed\n");
1426                         return rc;
1427                 }
1428         }
1429
1430         aparms.dir              = tbl->direction;
1431         aparms.type             = tbl->table_type;
1432         aparms.search_enable    = tbl->srch_b4_alloc;
1433         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1434         aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1435         aparms.tbl_scope_id     = tbl_scope_id;
1436
1437         /* All failures after the alloc succeeds require a free */
1438         rc = tf_alloc_tbl_entry(tfp, &aparms);
1439         if (rc) {
1440                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1441                             tbl->table_type,
1442                             (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1443                             rc);
1444                 return rc;
1445         }
1446
1447         /* Always storing values in Regfile in BE */
1448         idx = tfp_cpu_to_be_64(aparms.idx);
1449         rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1450         if (!rc) {
1451                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1452                             tbl->regfile_wr_idx);
1453                 goto error;
1454         }
1455
1456         if (!tbl->srch_b4_alloc) {
1457                 sparms.dir              = tbl->direction;
1458                 sparms.type             = tbl->table_type;
1459                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1460                 sparms.data_sz_in_bytes =
1461                         ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1462                 sparms.idx              = aparms.idx;
1463                 sparms.tbl_scope_id     = tbl_scope_id;
1464
1465                 rc = tf_set_tbl_entry(tfp, &sparms);
1466                 if (rc) {
1467                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1468                                     tbl->table_type,
1469                                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1470                                     sparms.idx,
1471                                     rc);
1472
1473                         goto error;
1474                 }
1475         }
1476
1477         /* Link the resource to the flow in the flow db */
1478         memset(&fid_parms, 0, sizeof(fid_parms));
1479         fid_parms.direction     = tbl->direction;
1480         fid_parms.resource_func = tbl->resource_func;
1481         fid_parms.resource_type = tbl->table_type;
1482         fid_parms.resource_hndl = aparms.idx;
1483         fid_parms.critical_resource     = 0;
1484
1485         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1486                                       parms->tbl_idx,
1487                                       parms->fid,
1488                                       &fid_parms);
1489         if (rc) {
1490                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1491                             rc);
1492                 goto error;
1493         }
1494
1495         return rc;
1496 error:
1497         /*
1498          * Free the allocated resource since we failed to either
1499          * write to the entry or link the flow
1500          */
1501         free_parms.dir  = tbl->direction;
1502         free_parms.type = tbl->table_type;
1503         free_parms.idx  = aparms.idx;
1504         free_parms.tbl_scope_id = tbl_scope_id;
1505
1506         trc = tf_free_tbl_entry(tfp, &free_parms);
1507         if (trc)
1508                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1509
1510         return rc;
1511 }
1512
1513 static int32_t
1514 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1515                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1516 {
1517         struct bnxt_ulp_mapper_class_key_field_info *kflds;
1518         struct bnxt_ulp_mapper_cache_entry *cache_entry;
1519         struct bnxt_ulp_mapper_ident_info *idents;
1520         uint32_t i, num_kflds = 0, num_idents = 0;
1521         struct ulp_flow_db_res_params fid_parms;
1522         struct tf_free_identifier_parms fparms;
1523         uint16_t tmplen, tmp_ident;
1524         struct ulp_blob key;
1525         uint8_t *cache_key;
1526         uint64_t regval;
1527         uint16_t *ckey;
1528         int32_t rc;
1529
1530         /* Get the key fields list and build the key. */
1531         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1532         if (!kflds || !num_kflds) {
1533                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1534                 return -EINVAL;
1535         }
1536         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order)) {
1537                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
1538                 return -EINVAL;
1539         }
1540         for (i = 0; i < num_kflds; i++) {
1541                 /* Setup the key */
1542                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1543                                                       &kflds[i],
1544                                                       &key, 1, "Cache Key");
1545                 if (rc) {
1546                         BNXT_TF_DBG(ERR,
1547                                     "Failed to create key for Cache rc=%d\n",
1548                                     rc);
1549                         return -EINVAL;
1550                 }
1551         }
1552
1553         /*
1554          * Perform the lookup in the cache table with constructed key.  The
1555          * cache_key is a byte array of tmplen, it needs to be converted to a
1556          * index for the cache table.
1557          */
1558         cache_key = ulp_blob_data_get(&key, &tmplen);
1559         ckey = (uint16_t *)cache_key;
1560         cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
1561                                                  tbl->cache_tbl_id,
1562                                                  *ckey);
1563
1564         /*
1565          * Get the identifier list for processing by both the hit and miss
1566          * processing.
1567          */
1568         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1569
1570         if (!cache_entry->ref_count) {
1571                 /* Initialize the cache entry */
1572                 cache_entry->tcam_idx = 0;
1573                 cache_entry->ref_count = 0;
1574                 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
1575                         cache_entry->idents[i] = ULP_IDENTS_INVALID;
1576
1577                 /* Need to allocate identifiers for storing in the cache. */
1578                 for (i = 0; i < num_idents; i++) {
1579                         /*
1580                          * Since we are using the cache, the identifier does not
1581                          * get added to the flow db.  Pass in the pointer to the
1582                          * tmp_ident.
1583                          */
1584                         rc = ulp_mapper_ident_process(parms, tbl,
1585                                                       &idents[i], &tmp_ident);
1586                         if (rc)
1587                                 goto error;
1588
1589                         cache_entry->ident_types[i] = idents[i].ident_type;
1590                         cache_entry->idents[i] = tmp_ident;
1591                 }
1592
1593                 /* Tell the TCAM processor to alloc an entry */
1594                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
1595                 /* Store the cache key for use by the tcam process code */
1596                 parms->cache_ptr = cache_entry;
1597         } else {
1598                 /* Cache hit, get values from result. */
1599                 for (i = 0; i < num_idents; i++) {
1600                         regval = (uint64_t)cache_entry->idents[i];
1601                         if (!ulp_regfile_write(parms->regfile,
1602                                                idents[i].regfile_wr_idx,
1603                                                tfp_cpu_to_be_64(regval))) {
1604                                 BNXT_TF_DBG(ERR,
1605                                             "Failed to write to regfile\n");
1606                                 return -EINVAL;
1607                         }
1608                 }
1609                 /*
1610                  * The cached entry is being used, so let the tcam processing
1611                  * know not to process this table.
1612                  */
1613                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
1614         }
1615
1616         /* Made through the cache processing, increment the reference count. */
1617         cache_entry->ref_count++;
1618
1619         /* Link the cache to the flow db. */
1620         memset(&fid_parms, 0, sizeof(fid_parms));
1621         fid_parms.direction = tbl->direction;
1622         fid_parms.resource_func = tbl->resource_func;
1623
1624         /*
1625          * Cache resource type is composed of both table_type and cache_tbl_id
1626          * need to set it appropriately via setter.
1627          */
1628         ulp_mapper_cache_res_type_set(&fid_parms,
1629                                       tbl->table_type,
1630                                       tbl->cache_tbl_id);
1631         fid_parms.resource_hndl = (uint64_t)*ckey;
1632         fid_parms.critical_resource = tbl->critical_resource;
1633         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1634                                       parms->tbl_idx,
1635                                       parms->fid,
1636                                       &fid_parms);
1637         if (rc)
1638                 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
1639
1640         return rc;
1641 error:
1642         /*
1643          * This error handling only gets called when the idents are being
1644          * allocated for the cache on misses.  Using the num_idents that was
1645          * previously set.
1646          */
1647         for (i = 0; i < num_idents; i++) {
1648                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
1649                         continue;
1650
1651                 fparms.dir = tbl->direction;
1652                 fparms.ident_type = idents[i].ident_type;
1653                 fparms.id = cache_entry->idents[i];
1654                 tf_free_identifier(parms->tfp, &fparms);
1655         }
1656
1657         return rc;
1658 }
1659
1660 /*
1661  * Function to process the action template. Iterate through the list
1662  * action info templates and process it.
1663  */
1664 static int32_t
1665 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1666 {
1667         uint32_t        i;
1668         int32_t         rc = 0;
1669
1670         if (!parms->atbls || !parms->num_atbls) {
1671                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1672                             parms->dev_id, parms->act_tid);
1673                 return -EINVAL;
1674         }
1675
1676         for (i = 0; i < parms->num_atbls; i++) {
1677                 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1678                 if (rc)
1679                         return rc;
1680         }
1681
1682         return rc;
1683 }
1684
1685 /* Create the classifier table entries for a flow. */
1686 static int32_t
1687 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1688 {
1689         uint32_t        i;
1690         int32_t         rc = 0;
1691
1692         if (!parms)
1693                 return -EINVAL;
1694
1695         if (!parms->ctbls || !parms->num_ctbls) {
1696                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1697                             parms->dev_id, parms->class_tid);
1698                 return -EINVAL;
1699         }
1700
1701         for (i = 0; i < parms->num_ctbls; i++) {
1702                 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1703
1704                 switch (tbl->resource_func) {
1705                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1706                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1707                         break;
1708                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1709                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1710                         break;
1711                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1712                         rc = ulp_mapper_index_tbl_process(parms, tbl);
1713                         break;
1714                 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1715                         rc = ulp_mapper_cache_tbl_process(parms, tbl);
1716                         break;
1717                 default:
1718                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1719                                     tbl->resource_func);
1720                         return -EINVAL;
1721                 }
1722
1723                 if (rc) {
1724                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1725                                     tbl->resource_func);
1726                         return rc;
1727                 }
1728         }
1729
1730         return rc;
1731 }
1732
1733 static int32_t
1734 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1735                          struct ulp_flow_db_res_params *res)
1736 {
1737         struct tf *tfp;
1738         int32_t rc = 0;
1739
1740         if (!res || !ulp) {
1741                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1742                 return -EINVAL;
1743         }
1744
1745         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1746         if (!tfp) {
1747                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1748                 return -EINVAL;
1749         }
1750
1751         switch (res->resource_func) {
1752         case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1753                 rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
1754                 break;
1755         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1756                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1757                 break;
1758         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1759                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1760                 break;
1761         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1762                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1763                 break;
1764         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1765                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1766                 break;
1767         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1768                 rc = ulp_mapper_mark_free(ulp, res);
1769                 break;
1770         default:
1771                 break;
1772         }
1773
1774         return rc;
1775 }
1776
1777 int32_t
1778 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
1779                           uint32_t fid,
1780                           enum bnxt_ulp_flow_db_tables  tbl_type)
1781 {
1782         struct ulp_flow_db_res_params   res_parms = { 0 };
1783         int32_t                         rc, trc;
1784
1785         if (!ulp_ctx) {
1786                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1787                 return -EINVAL;
1788         }
1789
1790         /*
1791          * Set the critical resource on the first resource del, then iterate
1792          * while status is good
1793          */
1794         res_parms.critical_resource = 1;
1795         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
1796
1797         if (rc) {
1798                 /*
1799                  * This is unexpected on the first call to resource del.
1800                  * It likely means that the flow did not exist in the flow db.
1801                  */
1802                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
1803                             tbl_type, fid, rc);
1804                 return rc;
1805         }
1806
1807         while (!rc) {
1808                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
1809                 if (trc)
1810                         /*
1811                          * On fail, we still need to attempt to free the
1812                          * remaining resources.  Don't return
1813                          */
1814                         BNXT_TF_DBG(ERR,
1815                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
1816                                     "] failed rc=%d.\n",
1817                                     tbl_type, fid, res_parms.resource_func,
1818                                     res_parms.resource_hndl, trc);
1819
1820                 /* All subsequent call require the critical_resource be zero */
1821                 res_parms.critical_resource = 0;
1822
1823                 rc = ulp_flow_db_resource_del(ulp_ctx,
1824                                               tbl_type,
1825                                               fid,
1826                                               &res_parms);
1827         }
1828
1829         /* Free the Flow ID since we've removed all resources */
1830         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
1831
1832         return rc;
1833 }
1834
1835 int32_t
1836 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
1837 {
1838         if (!ulp_ctx) {
1839                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1840                 return -EINVAL;
1841         }
1842
1843         return ulp_mapper_resources_free(ulp_ctx,
1844                                          fid,
1845                                          BNXT_ULP_REGULAR_FLOW_TABLE);
1846 }
1847
1848 /* Function to handle the mapping of the Flow to be compatible
1849  * with the underlying hardware.
1850  */
1851 int32_t
1852 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
1853                        struct bnxt_ulp_mapper_create_parms *cparms,
1854                        uint32_t *flowid)
1855 {
1856         struct bnxt_ulp_device_params *device_params;
1857         struct bnxt_ulp_mapper_parms parms;
1858         struct ulp_regfile regfile;
1859         int32_t  rc, trc;
1860
1861         if (!ulp_ctx || !cparms)
1862                 return -EINVAL;
1863
1864         /* Initialize the parms structure */
1865         memset(&parms, 0, sizeof(parms));
1866         parms.act_prop = cparms->act_prop;
1867         parms.act_bitmap = cparms->act;
1868         parms.regfile = &regfile;
1869         parms.hdr_field = cparms->hdr_field;
1870         parms.comp_fld = cparms->comp_fld;
1871         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1872         parms.ulp_ctx = ulp_ctx;
1873         parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1874
1875         /* Get the device id from the ulp context */
1876         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
1877                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
1878                 return -EINVAL;
1879         }
1880
1881         /*
1882          * Get the mapper data for dynamic mapper data such as default
1883          * ids.
1884          */
1885         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
1886                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
1887         if (!parms.mapper_data) {
1888                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
1889                 return -EINVAL;
1890         }
1891
1892         /* Get the action table entry from device id and act context id */
1893         parms.act_tid = cparms->act_tid;
1894         parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
1895                                                      parms.act_tid,
1896                                                      &parms.num_atbls);
1897         if (!parms.atbls || !parms.num_atbls) {
1898                 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
1899                             parms.dev_id, parms.act_tid);
1900                 return -EINVAL;
1901         }
1902
1903         /* Get the class table entry from device id and act context id */
1904         parms.class_tid = cparms->class_tid;
1905         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
1906                                                     parms.class_tid,
1907                                                     &parms.num_ctbls);
1908         if (!parms.ctbls || !parms.num_ctbls) {
1909                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1910                             parms.dev_id, parms.class_tid);
1911                 return -EINVAL;
1912         }
1913
1914         /* Get the byte order for the further processing from device params */
1915         device_params = bnxt_ulp_device_params_get(parms.dev_id);
1916         if (!device_params) {
1917                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1918                             parms.dev_id, parms.class_tid);
1919                 return -EINVAL;
1920         }
1921         parms.order = device_params->byte_order;
1922         parms.encap_byte_swap = device_params->encap_byte_swap;
1923
1924         /* initialize the registry file for further processing */
1925         if (!ulp_regfile_init(parms.regfile)) {
1926                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
1927                 return -EINVAL;
1928         }
1929
1930         rc = ulp_regfile_write(parms.regfile,
1931                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
1932                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
1933         if (!rc) {
1934                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
1935                 return -EINVAL;
1936         }
1937
1938         /* Allocate a Flow ID for attaching all resources for the flow to.
1939          * Once allocated, all errors have to walk the list of resources and
1940          * free each of them.
1941          */
1942         rc = ulp_flow_db_fid_alloc(ulp_ctx,
1943                                    BNXT_ULP_REGULAR_FLOW_TABLE,
1944                                    cparms->func_id,
1945                                    &parms.fid);
1946         if (rc) {
1947                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
1948                 return rc;
1949         }
1950
1951         /* Process the action template list from the selected action table*/
1952         rc = ulp_mapper_action_tbls_process(&parms);
1953         if (rc) {
1954                 BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n",
1955                             parms.dev_id, parms.act_tid);
1956                 goto flow_error;
1957         }
1958
1959         /* All good. Now process the class template */
1960         rc = ulp_mapper_class_tbls_process(&parms);
1961         if (rc) {
1962                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
1963                             parms.dev_id, parms.class_tid);
1964                 goto flow_error;
1965         }
1966
1967         *flowid = parms.fid;
1968
1969         return rc;
1970
1971 flow_error:
1972         /* Free all resources that were allocated during flow creation */
1973         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
1974         if (trc)
1975                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
1976
1977         return rc;
1978 }
1979
1980 int32_t
1981 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
1982 {
1983         struct bnxt_ulp_cache_tbl_params *tbl;
1984         struct tf_alloc_identifier_parms iparms;
1985         struct bnxt_ulp_mapper_data *data;
1986         struct bnxt_ulp_def_ident_info *dflt_ids;
1987         uint32_t i, num_dflt_ids, reg_idx;
1988         uint64_t regval;
1989         struct tf *tfp;
1990         int32_t rc, csize;
1991
1992         if (!ulp_ctx)
1993                 return -EINVAL;
1994
1995         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1996         if (!tfp)
1997                 return -EINVAL;
1998
1999         data = rte_zmalloc("ulp_mapper_data",
2000                            sizeof(struct bnxt_ulp_mapper_data), 0);
2001         if (!data) {
2002                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2003                 return -ENOMEM;
2004         }
2005
2006         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2007                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2008                 /* Don't call deinit since the prof_func wasn't allocated. */
2009                 rte_free(data);
2010                 return -ENOMEM;
2011         }
2012
2013         /* Allocate the default ids. */
2014         dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids);
2015         for (i = 0; i < num_dflt_ids; i++) {
2016                 iparms.ident_type = dflt_ids[i].ident_type;
2017                 iparms.dir = dflt_ids[i].direction;
2018
2019                 rc = tf_alloc_identifier(tfp, &iparms);
2020                 if (rc) {
2021                         BNXT_TF_DBG(ERR, "Failed to alloc dflt "
2022                                     "identifier [%s][%d]\n",
2023                                     (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
2024                                     iparms.ident_type);
2025                         goto error;
2026                 }
2027                 reg_idx = dflt_ids[i].def_regfile_index;
2028                 /* All regfile entries are stored as 64bit big-endian values. */
2029                 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
2030                 rc = ulp_mapper_def_regfile_write(data, iparms.dir,
2031                                                  reg_idx, regval);
2032                 if (rc) {
2033                         BNXT_TF_DBG(ERR, "Failed to write to default "
2034                                     "regfile.\n");
2035                         goto error;
2036                 }
2037         }
2038
2039         /* Allocate the ulp cache tables. */
2040         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2041                 tbl = ulp_mapper_cache_tbl_params_get(i);
2042                 if (!tbl) {
2043                         BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2044                                     i);
2045                         goto error;
2046                 }
2047                 if (tbl->num_entries != 0) {
2048                         csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2049                                 tbl->num_entries;
2050                         data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2051                                                          csize, 0);
2052                         if (!data->cache_tbl[i]) {
2053                                 BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2054                                             "table %d.\n", i);
2055                                 rc = -ENOMEM;
2056                                 goto error;
2057                         }
2058                 }
2059         }
2060
2061         return 0;
2062 error:
2063         /* Ignore the return code in favor of returning the original error. */
2064         ulp_mapper_deinit(ulp_ctx);
2065         return rc;
2066 }
2067
2068 void
2069 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2070 {
2071         struct tf_free_identifier_parms free_parms;
2072         struct bnxt_ulp_def_ident_info *dflt_ids;
2073         struct bnxt_ulp_mapper_data *data;
2074         uint32_t i, num_dflt_ids, reg_idx;
2075         enum tf_dir dir;
2076         uint64_t regval;
2077         struct tf *tfp;
2078
2079         if (!ulp_ctx) {
2080                 BNXT_TF_DBG(ERR,
2081                             "Failed to acquire ulp context, so data may "
2082                             "not be released.\n");
2083                 return;
2084         }
2085
2086         data = (struct bnxt_ulp_mapper_data *)
2087                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2088         if (!data) {
2089                 /* Go ahead and return since there is no allocated data. */
2090                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2091                 return;
2092         }
2093
2094         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2095         if (!tfp) {
2096                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2097                 /* Free the mapper data regardless of errors. */
2098                 goto free_mapper_data;
2099         }
2100
2101         /* Free the default prof func ids per direction. */
2102         dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids);
2103         for (i = 0; i < num_dflt_ids; i++) {
2104                 reg_idx = dflt_ids[i].def_regfile_index;
2105                 dir = dflt_ids[i].direction;
2106                 free_parms.ident_type = dflt_ids[i].ident_type;
2107                 free_parms.dir = dir;
2108                 if (ulp_mapper_def_regfile_read(data, dir, reg_idx, &regval)) {
2109                         BNXT_TF_DBG(ERR, "Failed to read def regfile to free "
2110                                     "identifier.\n");
2111                         continue;
2112                 }
2113                 /*
2114                  * All regfile entries are stored as 64bit big-endian.  Need
2115                  * to convert the value to cpu before calling tf.
2116                  */
2117                 regval = tfp_be_to_cpu_64(regval);
2118                 free_parms.id = (uint16_t)regval;
2119                 /* Ignore errors and free the remaining identifiers. */
2120                 tf_free_identifier(tfp, &free_parms);
2121         }
2122
2123 free_mapper_data:
2124         /* Free the ulp cache tables */
2125         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2126                 rte_free(data->cache_tbl[i]);
2127                 data->cache_tbl[i] = NULL;
2128         }
2129
2130         rte_free(data);
2131         /* Reset the data pointer within the ulp_ctx. */
2132         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
2133 }