b2c8c349c9650ba62fafb8f868e68f57126c4153
[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_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         if (is_gfid) {
34                 TF_GET_HASH_TYPE_FROM_GFID(fid, hashtype);
35                 TF_GET_HASH_INDEX_FROM_GFID(fid, idx);
36
37                 /* Need to truncate anything beyond supported flows */
38                 idx &= mtbl->gfid_mask;
39                 if (hashtype)
40                         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 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         if (!ctxt) {
61                 BNXT_TF_DBG(DEBUG, "Invalid ULP CTXT\n");
62                 return -EINVAL;
63         }
64
65         if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) {
66                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
67                 return -EINVAL;
68         }
69
70         dparms = bnxt_ulp_device_params_get(dev_id);
71         if (!dparms) {
72                 BNXT_TF_DBG(DEBUG, "Failed to device parms\n");
73                 return -EINVAL;
74         }
75
76         mark_tbl = rte_zmalloc("ulp_rx_mark_tbl_ptr",
77                                sizeof(struct bnxt_ulp_mark_tbl), 0);
78         if (!mark_tbl)
79                 goto mem_error;
80
81         /* Need to allocate 2 * Num flows to account for hash type bit.*/
82         mark_tbl->lfid_num_entries = dparms->mark_db_lfid_entries;
83         mark_tbl->lfid_tbl = rte_zmalloc("ulp_rx_em_flow_mark_table",
84                                          mark_tbl->lfid_num_entries *
85                                          sizeof(struct bnxt_lfid_mark_info),
86                                          0);
87         if (!mark_tbl->lfid_tbl)
88                 goto mem_error;
89
90         /* Need to allocate 2 * Num flows to account for hash type bit */
91         mark_tbl->gfid_num_entries = dparms->mark_db_gfid_entries;
92         if (!mark_tbl->gfid_num_entries)
93                 goto gfid_not_required;
94
95         mark_tbl->gfid_tbl = rte_zmalloc("ulp_rx_eem_flow_mark_table",
96                                          mark_tbl->gfid_num_entries *
97                                          sizeof(struct bnxt_gfid_mark_info),
98                                          0);
99         if (!mark_tbl->gfid_tbl)
100                 goto mem_error;
101
102         /*
103          * These values are used to compress the FID to the allowable index
104          * space.  The FID from hw may be the full hash which may be a big
105          * value to allocate and so allocate only needed hash values.
106          * gfid mask is the number of flow entries for the each left/right
107          * hash  The gfid type bit is used to get to the higher or lower hash
108          * entries.
109          */
110         mark_tbl->gfid_mask     = (mark_tbl->gfid_num_entries / 2) - 1;
111         mark_tbl->gfid_type_bit = (mark_tbl->gfid_num_entries / 2);
112
113         BNXT_TF_DBG(DEBUG, "GFID Max = 0x%08x\nGFID MASK = 0x%08x\n",
114                     mark_tbl->gfid_num_entries - 1,
115                     mark_tbl->gfid_mask);
116
117 gfid_not_required:
118         /* Add the mark tbl to the ulp context. */
119         bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, mark_tbl);
120         return 0;
121
122 mem_error:
123         rte_free(mark_tbl->gfid_tbl);
124         rte_free(mark_tbl->lfid_tbl);
125         rte_free(mark_tbl);
126         BNXT_TF_DBG(DEBUG, "Failed to allocate memory for mark mgr\n");
127         return -ENOMEM;
128 }
129
130 /*
131  * Release all resources in the Mark Manager for this ulp context
132  *
133  * ctxt [in] The ulp context for the mark manager
134  *
135  */
136 int32_t
137 ulp_mark_db_deinit(struct bnxt_ulp_context *ctxt)
138 {
139         struct bnxt_ulp_mark_tbl *mtbl;
140
141         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
142
143         if (mtbl) {
144                 rte_free(mtbl->gfid_tbl);
145                 rte_free(mtbl->lfid_tbl);
146                 rte_free(mtbl);
147
148                 /* Safe to ignore on deinit */
149                 (void)bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, NULL);
150         }
151
152         return 0;
153 }
154
155 /*
156  * Get a Mark from the Mark Manager
157  *
158  * ctxt [in] The ulp context for the mark manager
159  *
160  * is_gfid [in] The type of fid (GFID or LFID)
161  *
162  * fid [in] The flow id that is returned by HW in BD
163  *
164  * vfr_flag [out].it indicatesif mark is vfr_id or mark id
165  *
166  * mark [out] The mark that is associated with the FID
167  *
168  */
169 int32_t
170 ulp_mark_db_mark_get(struct bnxt_ulp_context *ctxt,
171                      bool is_gfid,
172                      uint32_t fid,
173                      uint32_t *vfr_flag,
174                      uint32_t *mark)
175 {
176         struct bnxt_ulp_mark_tbl *mtbl;
177         uint32_t idx = 0;
178
179         if (!ctxt || !mark)
180                 return -EINVAL;
181
182         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
183         if (!mtbl) {
184                 BNXT_TF_DBG(ERR, "Unable to get Mark Table\n");
185                 return -EINVAL;
186         }
187
188         idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
189
190         if (is_gfid) {
191                 if (idx >= mtbl->gfid_num_entries ||
192                     ULP_MARK_DB_ENTRY_IS_INVALID(&mtbl->gfid_tbl[idx]))
193                         return -EINVAL;
194
195                 BNXT_TF_DBG(DEBUG, "Get GFID[0x%0x] = 0x%0x\n",
196                             idx, mtbl->gfid_tbl[idx].mark_id);
197
198                 *vfr_flag = ULP_MARK_DB_ENTRY_IS_VFR_ID(&mtbl->gfid_tbl[idx]);
199                 *mark = mtbl->gfid_tbl[idx].mark_id;
200         } else {
201                 if (idx >= mtbl->lfid_num_entries ||
202                     ULP_MARK_DB_ENTRY_IS_INVALID(&mtbl->lfid_tbl[idx]))
203                         return -EINVAL;
204
205                 BNXT_TF_DBG(DEBUG, "Get LFID[0x%0x] = 0x%0x\n",
206                             idx, mtbl->lfid_tbl[idx].mark_id);
207
208                 *vfr_flag = ULP_MARK_DB_ENTRY_IS_VFR_ID(&mtbl->lfid_tbl[idx]);
209                 *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 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         if (!ctxt) {
238                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
239                 return -EINVAL;
240         }
241
242         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
243         if (!mtbl) {
244                 BNXT_TF_DBG(ERR, "Unable to get Mark DB\n");
245                 return -EINVAL;
246         }
247
248         is_gfid = (mark_flag & BNXT_ULP_MARK_GLOBAL_HW_FID);
249         if (is_gfid) {
250                 idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
251                 if (idx >= mtbl->gfid_num_entries) {
252                         BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
253                         return -EINVAL;
254                 }
255                 BNXT_TF_DBG(DEBUG, "Set GFID[0x%0x] = 0x%0x\n", idx, mark);
256                 mtbl->gfid_tbl[idx].mark_id = mark;
257                 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                 if (fid >= mtbl->lfid_num_entries) {
262                         BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
263                         return -EINVAL;
264                 }
265                 BNXT_TF_DBG(DEBUG, "Set LFID[0x%0x] = 0x%0x\n", fid, mark);
266                 mtbl->lfid_tbl[fid].mark_id = mark;
267                 ULP_MARK_DB_ENTRY_SET_VALID(&mtbl->lfid_tbl[fid]);
268
269                 if (mark_flag & BNXT_ULP_MARK_VFR_ID)
270                         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 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         if (!ctxt) {
296                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
297                 return -EINVAL;
298         }
299
300         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
301         if (!mtbl) {
302                 BNXT_TF_DBG(ERR, "Unable to get Mark DB\n");
303                 return -EINVAL;
304         }
305
306         is_gfid = (mark_flag & BNXT_ULP_MARK_GLOBAL_HW_FID);
307         if (is_gfid) {
308                 idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
309                 if (idx >= mtbl->gfid_num_entries) {
310                         BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
311                         return -EINVAL;
312                 }
313                 BNXT_TF_DBG(DEBUG, "Reset GFID[0x%0x]\n", idx);
314                 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                 if (fid >= mtbl->lfid_num_entries) {
320                         BNXT_TF_DBG(ERR, "Mark index greater than allocated\n");
321                         return -EINVAL;
322                 }
323                 memset(&mtbl->lfid_tbl[fid], 0,
324                        sizeof(struct bnxt_lfid_mark_info));
325         }
326
327         return 0;
328 }