xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_mark_mgr.c (revision b87abb2e55cbdd9fbf9d4f97ae86a097997d4be4)
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 }
272