837064eac3f3283b5b2099a1652c3466f4882be5
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_mark_mgr.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_common.h>
7 #include <rte_malloc.h>
8 #include <rte_log.h>
9 #include "bnxt.h"
10 #include "bnxt_ulp.h"
11 #include "tf_ext_flow_handle.h"
12 #include "ulp_mark_mgr.h"
13 #include "bnxt_tf_common.h"
14 #include "ulp_template_db.h"
15 #include "ulp_template_struct.h"
16
17 static inline uint32_t
18 ulp_mark_db_idx_get(bool is_gfid, uint32_t fid, struct bnxt_ulp_mark_tbl *mtbl)
19 {
20         uint32_t idx = 0, hashtype = 0;
21
22         if (is_gfid) {
23                 TF_GET_HASH_TYPE_FROM_GFID(fid, hashtype);
24                 TF_GET_HASH_INDEX_FROM_GFID(fid, idx);
25
26                 /* Need to truncate anything beyond supported flows */
27                 idx &= mtbl->gfid_mask;
28
29                 if (hashtype)
30                         idx |= mtbl->gfid_type_bit;
31         } else {
32                 idx = fid;
33         }
34
35         return idx;
36 }
37
38 static int32_t
39 ulp_mark_db_mark_set(struct bnxt_ulp_context *ctxt,
40                      bool is_gfid,
41                      uint32_t fid,
42                      uint32_t mark)
43 {
44         struct          bnxt_ulp_mark_tbl *mtbl;
45         uint32_t        idx = 0;
46
47         if (!ctxt) {
48                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
49                 return -EINVAL;
50         }
51
52         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
53         if (!mtbl) {
54                 BNXT_TF_DBG(ERR, "Unable to get Mark DB\n");
55                 return -EINVAL;
56         }
57
58         idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
59
60         if (is_gfid) {
61                 BNXT_TF_DBG(ERR, "Set GFID[0x%0x] = 0x%0x\n", idx, mark);
62
63                 mtbl->gfid_tbl[idx].mark_id = mark;
64                 mtbl->gfid_tbl[idx].valid = true;
65         } else {
66                 /* For the LFID, the FID is used as the index */
67                 mtbl->lfid_tbl[fid].mark_id = mark;
68                 mtbl->lfid_tbl[fid].valid = true;
69         }
70
71         return 0;
72 }
73
74 /*
75  * Allocate and Initialize all Mark Manager resources for this ulp context.
76  *
77  * ctxt [in] The ulp context for the mark manager.
78  *
79  */
80 int32_t
81 ulp_mark_db_init(struct bnxt_ulp_context *ctxt)
82 {
83         struct bnxt_ulp_device_params *dparms;
84         struct bnxt_ulp_mark_tbl *mark_tbl = NULL;
85         uint32_t dev_id;
86
87         if (!ctxt) {
88                 BNXT_TF_DBG(DEBUG, "Invalid ULP CTXT\n");
89                 return -EINVAL;
90         }
91
92         if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) {
93                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
94                 return -EINVAL;
95         }
96
97         dparms = bnxt_ulp_device_params_get(dev_id);
98         if (!dparms) {
99                 BNXT_TF_DBG(DEBUG, "Failed to device parms\n");
100                 return -EINVAL;
101         }
102
103         mark_tbl = rte_zmalloc("ulp_rx_mark_tbl_ptr",
104                                sizeof(struct bnxt_ulp_mark_tbl), 0);
105         if (!mark_tbl)
106                 goto mem_error;
107
108         /* Need to allocate 2 * Num flows to account for hash type bit. */
109         mark_tbl->lfid_tbl = rte_zmalloc("ulp_rx_em_flow_mark_table",
110                                          dparms->lfid_entries *
111                                             sizeof(struct bnxt_lfid_mark_info),
112                                          0);
113
114         if (!mark_tbl->lfid_tbl)
115                 goto mem_error;
116
117         /* Need to allocate 2 * Num flows to account for hash type bit. */
118         mark_tbl->gfid_tbl = rte_zmalloc("ulp_rx_eem_flow_mark_table",
119                                          2 * dparms->num_flows *
120                                             sizeof(struct bnxt_gfid_mark_info),
121                                          0);
122         if (!mark_tbl->gfid_tbl)
123                 goto mem_error;
124
125         /*
126          * TBD: This needs to be generalized for better mark handling
127          * These values are used to compress the FID to the allowable index
128          * space.  The FID from hw may be the full hash.
129          */
130         mark_tbl->gfid_max      = dparms->gfid_entries - 1;
131         mark_tbl->gfid_mask     = (dparms->gfid_entries / 2) - 1;
132         mark_tbl->gfid_type_bit = (dparms->gfid_entries / 2);
133
134         BNXT_TF_DBG(DEBUG, "GFID Max = 0x%08x\nGFID MASK = 0x%08x\n",
135                     mark_tbl->gfid_max,
136                     mark_tbl->gfid_mask);
137
138         /* Add the mart tbl to the ulp context. */
139         bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, mark_tbl);
140
141         return 0;
142
143 mem_error:
144         rte_free(mark_tbl->gfid_tbl);
145         rte_free(mark_tbl->lfid_tbl);
146         rte_free(mark_tbl);
147         BNXT_TF_DBG(DEBUG,
148                     "Failed to allocate memory for mark mgr\n");
149
150         return -ENOMEM;
151 }
152
153 /*
154  * Release all resources in the Mark Manager for this ulp context
155  *
156  * ctxt [in] The ulp context for the mark manager
157  *
158  */
159 int32_t
160 ulp_mark_db_deinit(struct bnxt_ulp_context *ctxt)
161 {
162         struct bnxt_ulp_mark_tbl *mtbl;
163
164         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
165
166         if (mtbl) {
167                 rte_free(mtbl->gfid_tbl);
168                 rte_free(mtbl->lfid_tbl);
169                 rte_free(mtbl);
170
171                 /* Safe to ignore on deinit */
172                 (void)bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, NULL);
173         }
174
175         return 0;
176 }
177
178 /*
179  * Adds a Mark to the Mark Manager
180  *
181  * ctxt [in] The ulp context for the mark manager
182  *
183  * is_gfid [in] The type of fid (GFID or LFID)
184  *
185  * fid [in] The flow id that is returned by HW in BD
186  *
187  * mark [in] The mark to be associated with the FID
188  *
189  */
190 int32_t
191 ulp_mark_db_mark_add(struct bnxt_ulp_context *ctxt,
192                      bool is_gfid,
193                      uint32_t gfid,
194                      uint32_t mark)
195 {
196         return ulp_mark_db_mark_set(ctxt, is_gfid, gfid, mark);
197 }