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