xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c (revision bdf4a3c6)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "tf_core.h"
9 #include "tfp.h"
10 #include "ulp_mapper.h"
11 #include "ulp_flow_db.h"
12 
13 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
14 #include "ulp_template_debug_proto.h"
15 #include "ulp_tf_debug.h"
16 #endif
17 
18 /* Retrieve the generic table  initialization parameters for the tbl_idx */
19 static struct bnxt_ulp_generic_tbl_params*
20 ulp_mapper_gen_tbl_params_get(uint32_t tbl_idx)
21 {
22 	if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ)
23 		return NULL;
24 
25 	return &ulp_generic_tbl_params[tbl_idx];
26 }
27 
28 /*
29  * Initialize the generic table list
30  *
31  * mapper_data [in] Pointer to the mapper data and the generic table is
32  * part of it
33  *
34  * returns 0 on success
35  */
36 int32_t
37 ulp_mapper_generic_tbl_list_init(struct bnxt_ulp_mapper_data *mapper_data)
38 {
39 	struct bnxt_ulp_generic_tbl_params *tbl;
40 	struct ulp_mapper_gen_tbl_list *entry;
41 	struct ulp_hash_create_params cparams;
42 	uint32_t idx, size;
43 
44 	/* Allocate the generic tables. */
45 	for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) {
46 		tbl = ulp_mapper_gen_tbl_params_get(idx);
47 		if (!tbl) {
48 			BNXT_TF_DBG(ERR, "Failed to get gen table parms %d\n",
49 				    idx);
50 			return -EINVAL;
51 		}
52 		entry = &mapper_data->gen_tbl_list[idx];
53 		if (tbl->result_num_entries != 0) {
54 			/* assign the name */
55 			entry->gen_tbl_name = tbl->name;
56 			/* add 4 bytes for reference count */
57 			entry->mem_data_size = (tbl->result_num_entries + 1) *
58 				(tbl->result_num_bytes + sizeof(uint32_t));
59 
60 			/* allocate the big chunk of memory */
61 			entry->mem_data = rte_zmalloc("ulp mapper gen tbl",
62 						      entry->mem_data_size, 0);
63 			if (!entry->mem_data) {
64 				BNXT_TF_DBG(ERR,
65 					    "%s:Failed to alloc gen table %d\n",
66 					    tbl->name, idx);
67 				return -ENOMEM;
68 			}
69 			/* Populate the generic table container */
70 			entry->container.num_elem = tbl->result_num_entries;
71 			entry->container.byte_data_size = tbl->result_num_bytes;
72 			entry->container.ref_count =
73 				(uint32_t *)entry->mem_data;
74 			size = sizeof(uint32_t) * (tbl->result_num_entries + 1);
75 			entry->container.byte_data = &entry->mem_data[size];
76 			entry->container.byte_order = tbl->result_byte_order;
77 		} else {
78 			BNXT_TF_DBG(ERR, "%s:Invalid gen table num of ent %d\n",
79 				    tbl->name, idx);
80 			return -EINVAL;
81 		}
82 		if (tbl->hash_tbl_entries) {
83 			cparams.key_size = tbl->key_num_bytes;
84 			cparams.num_buckets = tbl->num_buckets;
85 			cparams.num_hash_tbl_entries = tbl->hash_tbl_entries;
86 			cparams.num_key_entries = tbl->result_num_entries;
87 			if (ulp_gen_hash_tbl_list_init(&cparams,
88 						       &entry->hash_tbl)) {
89 				BNXT_TF_DBG(ERR,
90 					    "%s: Failed to alloc hash tbl %d\n",
91 					    tbl->name, idx);
92 				return -ENOMEM;
93 			}
94 		}
95 	}
96 	/* success */
97 	return 0;
98 }
99 
100 /*
101  * Free the generic table list
102  *
103  * mapper_data [in] Pointer to the mapper data and the generic table is
104  * part of it
105  *
106  * returns 0 on success
107  */
108 int32_t
109 ulp_mapper_generic_tbl_list_deinit(struct bnxt_ulp_mapper_data *mapper_data)
110 {
111 	struct ulp_mapper_gen_tbl_list *tbl_list;
112 	uint32_t idx;
113 
114 	/* iterate the generic table. */
115 	for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) {
116 		tbl_list = &mapper_data->gen_tbl_list[idx];
117 		if (tbl_list->mem_data) {
118 			rte_free(tbl_list->mem_data);
119 			tbl_list->mem_data = NULL;
120 		}
121 		if (tbl_list->hash_tbl) {
122 			ulp_gen_hash_tbl_list_deinit(tbl_list->hash_tbl);
123 			tbl_list->hash_tbl = NULL;
124 		}
125 	}
126 	/* success */
127 	return 0;
128 }
129 
130 /*
131  * Get the generic table list entry
132  *
133  * tbl_list [in] - Ptr to generic table
134  * key [in] - Key index to the table
135  * entry [out] - output will include the entry if found
136  *
137  * returns 0 on success.
138  */
139 int32_t
140 ulp_mapper_gen_tbl_entry_get(struct ulp_mapper_gen_tbl_list *tbl_list,
141 			     uint32_t key,
142 			     struct ulp_mapper_gen_tbl_entry *entry)
143 {
144 	/* populate the output and return the values */
145 	if (key > tbl_list->container.num_elem) {
146 		BNXT_TF_DBG(ERR, "%s: invalid key %x:%x\n",
147 			    tbl_list->gen_tbl_name, key,
148 			    tbl_list->container.num_elem);
149 		return -EINVAL;
150 	}
151 	entry->ref_count = &tbl_list->container.ref_count[key];
152 	entry->byte_data_size = tbl_list->container.byte_data_size;
153 	entry->byte_data = &tbl_list->container.byte_data[key *
154 		entry->byte_data_size];
155 	entry->byte_order = tbl_list->container.byte_order;
156 	return 0;
157 }
158 
159 /*
160  * utility function to calculate the table idx
161  *
162  * res_sub_type [in] - Resource sub type
163  * dir [in] - Direction
164  *
165  * returns None
166  */
167 int32_t
168 ulp_mapper_gen_tbl_idx_calculate(uint32_t res_sub_type, uint32_t dir)
169 {
170 	int32_t tbl_idx;
171 
172 	/* Validate for direction */
173 	if (dir >= TF_DIR_MAX) {
174 		BNXT_TF_DBG(ERR, "invalid argument %x\n", dir);
175 		return -EINVAL;
176 	}
177 	tbl_idx = (res_sub_type << 1) | (dir & 0x1);
178 	if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ) {
179 		BNXT_TF_DBG(ERR, "invalid table index %x\n", tbl_idx);
180 		return -EINVAL;
181 	}
182 	return tbl_idx;
183 }
184 
185 /*
186  * Set the data in the generic table entry, Data is in Big endian format
187  *
188  * entry [in] - generic table entry
189  * len [in] - The length of the data in bits to be set
190  * data [in] - pointer to the data to be used for setting the value.
191  * data_size [in] - length of the data pointer in bytes.
192  *
193  * returns 0 on success
194  */
195 int32_t
196 ulp_mapper_gen_tbl_entry_data_set(struct ulp_mapper_gen_tbl_entry *entry,
197 				  uint32_t len, uint8_t *data,
198 				  uint32_t data_size)
199 {
200 	/* validate the null arguments */
201 	if (!entry || !data) {
202 		BNXT_TF_DBG(ERR, "invalid argument\n");
203 		return -EINVAL;
204 	}
205 
206 	/* check the size of the buffer for validation */
207 	if (len > ULP_BYTE_2_BITS(entry->byte_data_size) ||
208 	    data_size < ULP_BITS_2_BYTE(len)) {
209 		BNXT_TF_DBG(ERR, "invalid offset or length %x:%x\n",
210 			    len, entry->byte_data_size);
211 		return -EINVAL;
212 	}
213 	memcpy(entry->byte_data, data, ULP_BITS_2_BYTE(len));
214 	return 0;
215 }
216 
217 /*
218  * Get the data in the generic table entry, Data is in Big endian format
219  *
220  * entry [in] - generic table entry
221  * offset [in] - The offset in bits where the data has to get
222  * len [in] - The length of the data in bits to be get
223  * data [out] - pointer to the data to be used for setting the value.
224  * data_size [in] - The size of data in bytes
225  *
226  * returns 0 on success
227  */
228 int32_t
229 ulp_mapper_gen_tbl_entry_data_get(struct ulp_mapper_gen_tbl_entry *entry,
230 				  uint32_t offset, uint32_t len, uint8_t *data,
231 				  uint32_t data_size)
232 {
233 	/* validate the null arguments */
234 	if (!entry || !data) {
235 		BNXT_TF_DBG(ERR, "invalid argument\n");
236 		return -EINVAL;
237 	}
238 
239 	/* check the size of the buffer for validation */
240 	if ((offset + len) > ULP_BYTE_2_BITS(entry->byte_data_size) ||
241 	    len > ULP_BYTE_2_BITS(data_size)) {
242 		BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
243 			    offset, len, entry->byte_data_size);
244 		return -EINVAL;
245 	}
246 	if (entry->byte_order == BNXT_ULP_BYTE_ORDER_LE)
247 		ulp_bs_pull_lsb(entry->byte_data, data, data_size, offset, len);
248 	else
249 		ulp_bs_pull_msb(entry->byte_data, data, offset, len);
250 
251 	return 0;
252 }
253 
254 /* Free the generic table list entry
255  *
256  * ulp_ctx [in] - Pointer to the ulp context
257  * tbl_idx [in] - Index of the generic table
258  * ckey [in] - Key for the entry in the table
259  *
260  * returns 0 on success
261  */
262 int32_t
263 ulp_mapper_gen_tbl_entry_free(struct bnxt_ulp_context *ulp_ctx,
264 			      uint32_t tbl_idx, uint32_t ckey)
265 {
266 	struct ulp_flow_db_res_params res;
267 
268 	res.direction = tbl_idx & 0x1;
269 	res.resource_sub_type = tbl_idx >> 1;
270 	res.resource_hndl = ckey;
271 
272 	return ulp_mapper_gen_tbl_res_free(ulp_ctx, &res);
273 }
274 
275 /* Free the generic table list resource
276  *
277  * ulp_ctx [in] - Pointer to the ulp context
278  * res [in] - Pointer to flow db resource entry
279  *
280  * returns 0 on success
281  */
282 int32_t
283 ulp_mapper_gen_tbl_res_free(struct bnxt_ulp_context *ulp_ctx,
284 			    struct ulp_flow_db_res_params *res)
285 {
286 	struct bnxt_ulp_mapper_data *mapper_data;
287 	struct ulp_mapper_gen_tbl_list *gen_tbl_list;
288 	struct ulp_mapper_gen_tbl_entry entry;
289 	struct ulp_gen_hash_entry_params hash_entry;
290 	int32_t tbl_idx;
291 	uint32_t fid = 0;
292 	uint32_t key_idx;
293 
294 	/* Extract the resource sub type and direction */
295 	tbl_idx = ulp_mapper_gen_tbl_idx_calculate(res->resource_sub_type,
296 						   res->direction);
297 	if (tbl_idx < 0) {
298 		BNXT_TF_DBG(ERR, "invalid argument %x:%x\n",
299 			    res->resource_sub_type, res->direction);
300 		return -EINVAL;
301 	}
302 
303 	mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
304 	if (!mapper_data) {
305 		BNXT_TF_DBG(ERR, "invalid ulp context %x\n", tbl_idx);
306 		return -EINVAL;
307 	}
308 	/* get the generic table  */
309 	gen_tbl_list = &mapper_data->gen_tbl_list[tbl_idx];
310 
311 	/* Get the generic table entry*/
312 	if (gen_tbl_list->hash_tbl) {
313 		/* use the hash index to get the value */
314 		hash_entry.hash_index = (uint32_t)res->resource_hndl;
315 		if (ulp_gen_hash_tbl_list_index_search(gen_tbl_list->hash_tbl,
316 						       &hash_entry)) {
317 			BNXT_TF_DBG(ERR, "Unable to find has entry %x:%x\n",
318 				    tbl_idx, hash_entry.hash_index);
319 			return -EINVAL;
320 		}
321 		key_idx = hash_entry.key_idx;
322 
323 	} else {
324 		key_idx =  (uint32_t)res->resource_hndl;
325 	}
326 	if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_idx, &entry)) {
327 		BNXT_TF_DBG(ERR, "Gen tbl entry get failed %x:%" PRIX64 "\n",
328 			    tbl_idx, res->resource_hndl);
329 		return -EINVAL;
330 	}
331 
332 	/* Decrement the reference count */
333 	if (!ULP_GEN_TBL_REF_CNT(&entry)) {
334 		BNXT_TF_DBG(ERR, "generic table corrupt %x:%" PRIX64 "\n",
335 			    tbl_idx, res->resource_hndl);
336 		return -EINVAL;
337 	}
338 	ULP_GEN_TBL_REF_CNT_DEC(&entry);
339 
340 	/* retain the details since there are other users */
341 	if (ULP_GEN_TBL_REF_CNT(&entry))
342 		return 0;
343 
344 	/* Delete the generic table entry. First extract the fid */
345 	if (ulp_mapper_gen_tbl_entry_data_get(&entry, ULP_GEN_TBL_FID_OFFSET,
346 					      ULP_GEN_TBL_FID_SIZE_BITS,
347 					      (uint8_t *)&fid,
348 					      sizeof(fid))) {
349 		BNXT_TF_DBG(ERR, "Unable to get fid %x:%" PRIX64 "\n",
350 			    tbl_idx, res->resource_hndl);
351 		return -EINVAL;
352 	}
353 	fid = tfp_be_to_cpu_32(fid);
354 	/* no need to del if fid is 0 since there is no associated resource */
355 	if (fid) {
356 		/* Destroy the flow associated with the shared flow id */
357 		if (ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_RID,
358 					    fid))
359 			BNXT_TF_DBG(ERR,
360 				    "Error in deleting shared flow id %x\n",
361 				    fid);
362 	}
363 
364 	/* Delete the entry from the hash table */
365 	if (gen_tbl_list->hash_tbl)
366 		ulp_gen_hash_tbl_list_del(gen_tbl_list->hash_tbl, &hash_entry);
367 
368 	/* clear the byte data of the generic table entry */
369 	memset(entry.byte_data, 0, entry.byte_data_size);
370 
371 	return 0;
372 }
373 
374 /*
375  * Write the generic table list hash entry
376  *
377  * tbl_list [in] - pointer to the generic table list
378  * hash_entry [in] -  Hash table entry
379  * gen_tbl_ent [out] - generic table entry
380  *
381  * returns 0 on success.
382  */
383 int32_t
384 ulp_mapper_gen_tbl_hash_entry_add(struct ulp_mapper_gen_tbl_list *tbl_list,
385 				  struct ulp_gen_hash_entry_params *hash_entry,
386 				  struct ulp_mapper_gen_tbl_entry *gen_tbl_ent)
387 {
388 	uint32_t key;
389 	int32_t rc = 0;
390 
391 	switch (hash_entry->search_flag) {
392 	case ULP_GEN_HASH_SEARCH_FOUND:
393 		BNXT_TF_DBG(ERR, "%s: gen hash entry already present\n",
394 			    tbl_list->gen_tbl_name);
395 		return -EINVAL;
396 	case ULP_GEN_HASH_SEARCH_FULL:
397 		BNXT_TF_DBG(ERR, "%s: gen hash table is full\n",
398 			    tbl_list->gen_tbl_name);
399 		return -EINVAL;
400 	case ULP_GEN_HASH_SEARCH_MISSED:
401 		rc = ulp_gen_hash_tbl_list_add(tbl_list->hash_tbl, hash_entry);
402 		if (rc) {
403 			BNXT_TF_DBG(ERR, "%s: gen hash table add failed\n",
404 				    tbl_list->gen_tbl_name);
405 			return -EINVAL;
406 		}
407 		key = hash_entry->key_idx;
408 		gen_tbl_ent->ref_count = &tbl_list->container.ref_count[key];
409 		gen_tbl_ent->byte_data_size =
410 			tbl_list->container.byte_data_size;
411 		gen_tbl_ent->byte_data = &tbl_list->container.byte_data[key *
412 			gen_tbl_ent->byte_data_size];
413 		gen_tbl_ent->byte_order = tbl_list->container.byte_order;
414 		break;
415 	default:
416 		BNXT_TF_DBG(ERR, "%s: invalid search flag\n",
417 			    tbl_list->gen_tbl_name);
418 		return -EINVAL;
419 	}
420 
421 	return rc;
422 }
423