Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2014-2023 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_enum.h"
15 : : #include "ulp_template_struct.h"
16 : :
17 : : #define ULP_MARK_DB_ENTRY_SET_VALID(mark_info) ((mark_info)->flags |=\
18 : : BNXT_ULP_MARK_VALID)
19 : : #define ULP_MARK_DB_ENTRY_IS_INVALID(mark_info) (!((mark_info)->flags &\
20 : : BNXT_ULP_MARK_VALID))
21 : : #define ULP_MARK_DB_ENTRY_SET_VFR_ID(mark_info) ((mark_info)->flags |=\
22 : : BNXT_ULP_MARK_VFR_ID)
23 : : #define ULP_MARK_DB_ENTRY_IS_VFR_ID(mark_info) ((mark_info)->flags &\
24 : : BNXT_ULP_MARK_VFR_ID)
25 : : #define ULP_MARK_DB_ENTRY_IS_GLOBAL_HW_FID(mark_info) ((mark_info)->flags &\
26 : : BNXT_ULP_MARK_GLOBAL_HW_FID)
27 : :
28 : : static inline uint32_t
29 : : ulp_mark_db_idx_get(bool is_gfid, uint32_t fid, struct bnxt_ulp_mark_tbl *mtbl)
30 : : {
31 : : uint32_t idx = 0, hashtype = 0;
32 : :
33 [ # # ]: 0 : if (is_gfid) {
34 : 0 : TF_GET_HASH_TYPE_FROM_GFID(fid, hashtype);
35 : 0 : TF_GET_HASH_INDEX_FROM_GFID(fid, idx);
36 : :
37 : : /* Need to truncate anything beyond supported flows */
38 : 0 : idx &= mtbl->gfid_mask;
39 [ # # # # : 0 : if (hashtype)
# # ]
40 : 0 : idx |= mtbl->gfid_type_bit;
41 : : } else {
42 : : idx = fid;
43 : : }
44 : : return idx;
45 : : }
46 : :
47 : : /*
48 : : * Allocate and Initialize all Mark Manager resources for this ulp context.
49 : : *
50 : : * ctxt [in] The ulp context for the mark manager.
51 : : *
52 : : */
53 : : int32_t
54 : 0 : ulp_mark_db_init(struct bnxt_ulp_context *ctxt)
55 : : {
56 : : struct bnxt_ulp_device_params *dparms;
57 : : struct bnxt_ulp_mark_tbl *mark_tbl = NULL;
58 : : uint32_t dev_id;
59 : :
60 [ # # ]: 0 : if (!ctxt) {
61 : 0 : BNXT_TF_DBG(DEBUG, "Invalid ULP CTXT\n");
62 : 0 : return -EINVAL;
63 : : }
64 : :
65 [ # # ]: 0 : if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) {
66 : 0 : BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
67 : 0 : return -EINVAL;
68 : : }
69 : :
70 : 0 : dparms = bnxt_ulp_device_params_get(dev_id);
71 [ # # ]: 0 : if (!dparms) {
72 : 0 : BNXT_TF_DBG(DEBUG, "Failed to device parms\n");
73 : 0 : return -EINVAL;
74 : : }
75 : :
76 [ # # # # ]: 0 : if (!dparms->mark_db_lfid_entries || !dparms->mark_db_gfid_entries) {
77 : 0 : BNXT_TF_DBG(DEBUG, "mark Table is not allocated\n");
78 : 0 : bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, NULL);
79 : 0 : return 0;
80 : : }
81 : :
82 : 0 : mark_tbl = rte_zmalloc("ulp_rx_mark_tbl_ptr",
83 : : sizeof(struct bnxt_ulp_mark_tbl), 0);
84 [ # # ]: 0 : if (!mark_tbl)
85 : 0 : goto mem_error;
86 : :
87 : : /* Need to allocate 2 * Num flows to account for hash type bit.*/
88 : 0 : mark_tbl->lfid_num_entries = dparms->mark_db_lfid_entries;
89 : 0 : mark_tbl->lfid_tbl = rte_zmalloc("ulp_rx_em_flow_mark_table",
90 : 0 : mark_tbl->lfid_num_entries *
91 : : sizeof(struct bnxt_lfid_mark_info),
92 : : 0);
93 [ # # ]: 0 : if (!mark_tbl->lfid_tbl)
94 : 0 : goto mem_error;
95 : :
96 : : /* Need to allocate 2 * Num flows to account for hash type bit */
97 : 0 : mark_tbl->gfid_num_entries = dparms->mark_db_gfid_entries;
98 [ # # ]: 0 : if (!mark_tbl->gfid_num_entries)
99 : 0 : goto gfid_not_required;
100 : :
101 : 0 : mark_tbl->gfid_tbl = rte_zmalloc("ulp_rx_eem_flow_mark_table",
102 : 0 : mark_tbl->gfid_num_entries *
103 : : sizeof(struct bnxt_gfid_mark_info),
104 : : 0);
105 [ # # ]: 0 : if (!mark_tbl->gfid_tbl)
106 : 0 : goto mem_error;
107 : :
108 : : /*
109 : : * These values are used to compress the FID to the allowable index
110 : : * space. The FID from hw may be the full hash which may be a big
111 : : * value to allocate and so allocate only needed hash values.
112 : : * gfid mask is the number of flow entries for the each left/right
113 : : * hash The gfid type bit is used to get to the higher or lower hash
114 : : * entries.
115 : : */
116 : 0 : mark_tbl->gfid_mask = (mark_tbl->gfid_num_entries / 2) - 1;
117 : 0 : mark_tbl->gfid_type_bit = (mark_tbl->gfid_num_entries / 2);
118 : :
119 : 0 : BNXT_TF_DBG(DEBUG, "GFID Max = 0x%08x GFID MASK = 0x%08x\n",
120 : : mark_tbl->gfid_num_entries - 1,
121 : : mark_tbl->gfid_mask);
122 : :
123 : 0 : gfid_not_required:
124 : : /* Add the mark tbl to the ulp context. */
125 : 0 : bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, mark_tbl);
126 : 0 : return 0;
127 : :
128 : 0 : mem_error:
129 [ # # ]: 0 : if (mark_tbl) {
130 : 0 : rte_free(mark_tbl->gfid_tbl);
131 : 0 : rte_free(mark_tbl->lfid_tbl);
132 : 0 : rte_free(mark_tbl);
133 : : }
134 : 0 : BNXT_TF_DBG(DEBUG, "Failed to allocate memory for mark mgr\n");
135 : 0 : return -ENOMEM;
136 : : }
137 : :
138 : : /*
139 : : * Release all resources in the Mark Manager for this ulp context
140 : : *
141 : : * ctxt [in] The ulp context for the mark manager
142 : : *
143 : : */
144 : : int32_t
145 : 0 : ulp_mark_db_deinit(struct bnxt_ulp_context *ctxt)
146 : : {
147 : : struct bnxt_ulp_mark_tbl *mtbl;
148 : :
149 : 0 : mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
150 : :
151 [ # # ]: 0 : if (mtbl) {
152 : 0 : rte_free(mtbl->gfid_tbl);
153 : 0 : rte_free(mtbl->lfid_tbl);
154 : 0 : rte_free(mtbl);
155 : :
156 : : /* Safe to ignore on deinit */
157 : 0 : (void)bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, NULL);
158 : : }
159 : :
160 : 0 : return 0;
161 : : }
162 : :
163 : : /*
164 : : * Get a Mark from the Mark Manager
165 : : *
166 : : * ctxt [in] The ulp context for the mark manager
167 : : *
168 : : * is_gfid [in] The type of fid (GFID or LFID)
169 : : *
170 : : * fid [in] The flow id that is returned by HW in BD
171 : : *
172 : : * vfr_flag [out].it indicatesif mark is vfr_id or mark id
173 : : *
174 : : * mark [out] The mark that is associated with the FID
175 : : *
176 : : */
177 : : int32_t
178 : 0 : ulp_mark_db_mark_get(struct bnxt_ulp_context *ctxt,
179 : : bool is_gfid,
180 : : uint32_t fid,
181 : : uint32_t *vfr_flag,
182 : : uint32_t *mark)
183 : : {
184 : : struct bnxt_ulp_mark_tbl *mtbl;
185 : : uint32_t idx = 0;
186 : :
187 [ # # ]: 0 : if (!ctxt || !mark)
188 : : return -EINVAL;
189 : :
190 : 0 : mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
191 [ # # ]: 0 : if (!mtbl)
192 : : return -EINVAL;
193 : :
194 : : idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
195 : :
196 [ # # ]: 0 : if (is_gfid) {
197 [ # # ]: 0 : if (idx >= mtbl->gfid_num_entries ||
198 [ # # ]: 0 : ULP_MARK_DB_ENTRY_IS_INVALID(&mtbl->gfid_tbl[idx]))
199 : : return -EINVAL;
200 : :
201 : 0 : *vfr_flag = ULP_MARK_DB_ENTRY_IS_VFR_ID(&mtbl->gfid_tbl[idx]);
202 : 0 : *mark = mtbl->gfid_tbl[idx].mark_id;
203 : : } else {
204 [ # # ]: 0 : if (idx >= mtbl->lfid_num_entries ||
205 [ # # ]: 0 : ULP_MARK_DB_ENTRY_IS_INVALID(&mtbl->lfid_tbl[idx]))
206 : : return -EINVAL;
207 : :
208 : 0 : *vfr_flag = ULP_MARK_DB_ENTRY_IS_VFR_ID(&mtbl->lfid_tbl[idx]);
209 : 0 : *mark = mtbl->lfid_tbl[idx].mark_id;
210 : : }
211 : :
212 : : return 0;
213 : : }
214 : :
215 : : /*
216 : : * Adds a Mark to the Mark Manager
217 : : *
218 : : * ctxt [in] The ulp context for the mark manager
219 : : *
220 : : * mark_flag [in] mark flags.
221 : : *
222 : : * fid [in] The flow id that is returned by HW in BD
223 : : *
224 : : * mark [in] The mark to be associated with the FID
225 : : *
226 : : */
227 : : int32_t
228 : 0 : ulp_mark_db_mark_add(struct bnxt_ulp_context *ctxt,
229 : : uint32_t mark_flag,
230 : : uint32_t fid,
231 : : uint32_t mark)
232 : : {
233 : : struct bnxt_ulp_mark_tbl *mtbl;
234 : : uint32_t idx = 0;
235 : : bool is_gfid;
236 : :
237 [ # # ]: 0 : if (!ctxt) {
238 : 0 : BNXT_TF_DBG(ERR, "Invalid ulp context\n");
239 : 0 : return -EINVAL;
240 : : }
241 : :
242 : 0 : mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
243 [ # # ]: 0 : if (!mtbl) {
244 : 0 : BNXT_TF_DBG(ERR, "Unable to get Mark DB\n");
245 : 0 : return -EINVAL;
246 : : }
247 : :
248 : 0 : is_gfid = (mark_flag & BNXT_ULP_MARK_GLOBAL_HW_FID);
249 [ # # ]: 0 : if (is_gfid) {
250 : : idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
251 [ # # ]: 0 : if (idx >= mtbl->gfid_num_entries) {
252 : 0 : BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
253 : 0 : return -EINVAL;
254 : : }
255 : 0 : BNXT_TF_DBG(DEBUG, "Set GFID[0x%0x] = 0x%0x\n", idx, mark);
256 : 0 : mtbl->gfid_tbl[idx].mark_id = mark;
257 : 0 : ULP_MARK_DB_ENTRY_SET_VALID(&mtbl->gfid_tbl[idx]);
258 : :
259 : : } else {
260 : : /* For the LFID, the FID is used as the index */
261 [ # # ]: 0 : if (fid >= mtbl->lfid_num_entries) {
262 : 0 : BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
263 : 0 : return -EINVAL;
264 : : }
265 : 0 : BNXT_TF_DBG(DEBUG, "Set LFID[0x%0x] = 0x%0x\n", fid, mark);
266 : 0 : mtbl->lfid_tbl[fid].mark_id = mark;
267 : 0 : ULP_MARK_DB_ENTRY_SET_VALID(&mtbl->lfid_tbl[fid]);
268 : :
269 [ # # ]: 0 : if (mark_flag & BNXT_ULP_MARK_VFR_ID)
270 : 0 : ULP_MARK_DB_ENTRY_SET_VFR_ID(&mtbl->lfid_tbl[fid]);
271 : : }
272 : :
273 : : return 0;
274 : : }
275 : :
276 : : /*
277 : : * Removes a Mark from the Mark Manager
278 : : *
279 : : * ctxt [in] The ulp context for the mark manager
280 : : *
281 : : * mark_flag [in] mark flags.
282 : : *
283 : : * fid [in] The flow id that is returned by HW in BD
284 : : *
285 : : */
286 : : int32_t
287 : 0 : ulp_mark_db_mark_del(struct bnxt_ulp_context *ctxt,
288 : : uint32_t mark_flag,
289 : : uint32_t fid)
290 : : {
291 : : struct bnxt_ulp_mark_tbl *mtbl;
292 : : uint32_t idx = 0;
293 : : bool is_gfid;
294 : :
295 [ # # ]: 0 : if (!ctxt) {
296 : 0 : BNXT_TF_DBG(ERR, "Invalid ulp context\n");
297 : 0 : return -EINVAL;
298 : : }
299 : :
300 : 0 : mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
301 [ # # ]: 0 : if (!mtbl) {
302 : 0 : BNXT_TF_DBG(ERR, "Unable to get Mark DB\n");
303 : 0 : return -EINVAL;
304 : : }
305 : :
306 : 0 : is_gfid = (mark_flag & BNXT_ULP_MARK_GLOBAL_HW_FID);
307 [ # # ]: 0 : if (is_gfid) {
308 : : idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
309 [ # # ]: 0 : if (idx >= mtbl->gfid_num_entries) {
310 : 0 : BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
311 : 0 : return -EINVAL;
312 : : }
313 : 0 : BNXT_TF_DBG(DEBUG, "Reset GFID[0x%0x]\n", idx);
314 : 0 : memset(&mtbl->gfid_tbl[idx], 0,
315 : : sizeof(struct bnxt_gfid_mark_info));
316 : :
317 : : } else {
318 : : /* For the LFID, the FID is used as the index */
319 [ # # ]: 0 : if (fid >= mtbl->lfid_num_entries) {
320 : 0 : BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
321 : 0 : return -EINVAL;
322 : : }
323 : 0 : memset(&mtbl->lfid_tbl[fid], 0,
324 : : sizeof(struct bnxt_lfid_mark_info));
325 : : }
326 : :
327 : : return 0;
328 : : }
|