net/bnxt: support marking packet
[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(DEBUG, "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 mark 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  * Get a Mark from 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 [out] The mark that is associated with the FID
188  *
189  */
190 int32_t
191 ulp_mark_db_mark_get(struct bnxt_ulp_context *ctxt,
192                      bool is_gfid,
193                      uint32_t fid,
194                      uint32_t *mark)
195 {
196         struct bnxt_ulp_mark_tbl *mtbl;
197         uint32_t idx = 0;
198
199         if (!ctxt || !mark)
200                 return -EINVAL;
201
202         mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt);
203         if (!mtbl) {
204                 BNXT_TF_DBG(ERR, "Unable to get Mark Table\n");
205                 return -EINVAL;
206         }
207
208         idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl);
209
210         if (is_gfid) {
211                 if (!mtbl->gfid_tbl[idx].valid)
212                         return -EINVAL;
213
214                 BNXT_TF_DBG(DEBUG, "Get GFID[0x%0x] = 0x%0x\n",
215                             idx, mtbl->gfid_tbl[idx].mark_id);
216
217                 *mark = mtbl->gfid_tbl[idx].mark_id;
218         } else {
219                 if (!mtbl->gfid_tbl[idx].valid)
220                         return -EINVAL;
221
222                 BNXT_TF_DBG(DEBUG, "Get LFID[0x%0x] = 0x%0x\n",
223                             idx, mtbl->lfid_tbl[idx].mark_id);
224
225                 *mark = mtbl->lfid_tbl[idx].mark_id;
226         }
227
228         return 0;
229 }
230
231 /*
232  * Adds a Mark to the Mark Manager
233  *
234  * ctxt [in] The ulp context for the mark manager
235  *
236  * is_gfid [in] The type of fid (GFID or LFID)
237  *
238  * fid [in] The flow id that is returned by HW in BD
239  *
240  * mark [in] The mark to be associated with the FID
241  *
242  */
243 int32_t
244 ulp_mark_db_mark_add(struct bnxt_ulp_context *ctxt,
245                      bool is_gfid,
246                      uint32_t gfid,
247                      uint32_t mark)
248 {
249         return ulp_mark_db_mark_set(ctxt, is_gfid, gfid, mark);
250 }
251
252 /*
253  * Removes a Mark from the Mark Manager
254  *
255  * ctxt [in] The ulp context for the mark manager
256  *
257  * is_gfid [in] The type of fid (GFID or LFID)
258  *
259  * fid [in] The flow id that is returned by HW in BD
260  *
261  * mark [in] The mark to be associated with the FID
262  *
263  */
264 int32_t
265 ulp_mark_db_mark_del(struct bnxt_ulp_context *ctxt,
266                      bool is_gfid,
267                      uint32_t gfid,
268                      uint32_t mark  __rte_unused)
269 {
270         return ulp_mark_db_mark_set(ctxt, is_gfid, gfid, ULP_MARK_INVALID);
271 }