xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_port_db.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_malloc.h>
7 #include "bnxt.h"
8 #include "bnxt_vnic.h"
9 #include "bnxt_tf_common.h"
10 #include "ulp_port_db.h"
11 
12 static uint32_t
13 ulp_port_db_allocate_ifindex(struct bnxt_ulp_port_db *port_db)
14 {
15 	uint32_t idx = 1;
16 
17 	while (idx < port_db->ulp_intf_list_size &&
18 	       port_db->ulp_intf_list[idx].type != BNXT_ULP_INTF_TYPE_INVALID)
19 		idx++;
20 
21 	if (idx >= port_db->ulp_intf_list_size) {
22 		BNXT_TF_DBG(ERR, "Port DB interface list is full\n");
23 		return 0;
24 	}
25 	return idx;
26 }
27 
28 /*
29  * Initialize the port database. Memory is allocated in this
30  * call and assigned to the port database.
31  *
32  * ulp_ctxt [in] Ptr to ulp context
33  *
34  * Returns 0 on success or negative number on failure.
35  */
36 int32_t	ulp_port_db_init(struct bnxt_ulp_context *ulp_ctxt, uint8_t port_cnt)
37 {
38 	struct bnxt_ulp_port_db *port_db;
39 
40 	port_db = rte_zmalloc("bnxt_ulp_port_db",
41 			      sizeof(struct bnxt_ulp_port_db), 0);
42 	if (!port_db) {
43 		BNXT_TF_DBG(ERR,
44 			    "Failed to allocate memory for port db\n");
45 		return -ENOMEM;
46 	}
47 
48 	/* Attach the port database to the ulp context. */
49 	bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, port_db);
50 
51 	/* index 0 is not being used hence add 1 to size */
52 	port_db->ulp_intf_list_size = BNXT_PORT_DB_MAX_INTF_LIST + 1;
53 	/* Allocate the port tables */
54 	port_db->ulp_intf_list = rte_zmalloc("bnxt_ulp_port_db_intf_list",
55 					     port_db->ulp_intf_list_size *
56 					     sizeof(struct ulp_interface_info),
57 					     0);
58 	if (!port_db->ulp_intf_list) {
59 		BNXT_TF_DBG(ERR,
60 			    "Failed to allocate mem for port interface list\n");
61 		goto error_free;
62 	}
63 
64 	/* Allocate the phy port list */
65 	port_db->phy_port_list = rte_zmalloc("bnxt_ulp_phy_port_list",
66 					     port_cnt *
67 					     sizeof(struct ulp_phy_port_info),
68 					     0);
69 	if (!port_db->phy_port_list) {
70 		BNXT_TF_DBG(ERR,
71 			    "Failed to allocate mem for phy port list\n");
72 		goto error_free;
73 	}
74 	port_db->phy_port_cnt = port_cnt;
75 	return 0;
76 
77 error_free:
78 	ulp_port_db_deinit(ulp_ctxt);
79 	return -ENOMEM;
80 }
81 
82 /*
83  * Deinitialize the port database. Memory is deallocated in
84  * this call.
85  *
86  * ulp_ctxt [in] Ptr to ulp context
87  *
88  * Returns 0 on success.
89  */
90 int32_t	ulp_port_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
91 {
92 	struct bnxt_ulp_port_db *port_db;
93 
94 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
95 	if (!port_db) {
96 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
97 		return -EINVAL;
98 	}
99 
100 	/* Detach the flow database from the ulp context. */
101 	bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, NULL);
102 
103 	/* Free up all the memory. */
104 	rte_free(port_db->phy_port_list);
105 	rte_free(port_db->ulp_intf_list);
106 	rte_free(port_db);
107 	return 0;
108 }
109 
110 /*
111  * Update the port database.This api is called when the port
112  * details are available during the startup.
113  *
114  * ulp_ctxt [in] Ptr to ulp context
115  * bp [in]. ptr to the device function.
116  *
117  * Returns 0 on success or negative number on failure.
118  */
119 int32_t	ulp_port_db_dev_port_intf_update(struct bnxt_ulp_context *ulp_ctxt,
120 					 struct rte_eth_dev *eth_dev)
121 {
122 	uint32_t port_id = eth_dev->data->port_id;
123 	struct ulp_phy_port_info *port_data;
124 	struct bnxt_ulp_port_db *port_db;
125 	struct ulp_interface_info *intf;
126 	struct ulp_func_if_info *func;
127 	uint32_t ifindex;
128 	int32_t rc;
129 
130 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
131 	if (!port_db) {
132 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
133 		return -EINVAL;
134 	}
135 
136 	rc = ulp_port_db_dev_port_to_ulp_index(ulp_ctxt, port_id, &ifindex);
137 	if (rc == -ENOENT) {
138 		/* port not found, allocate one */
139 		ifindex = ulp_port_db_allocate_ifindex(port_db);
140 		if (!ifindex)
141 			return -ENOMEM;
142 		port_db->dev_port_list[port_id] = ifindex;
143 	} else if (rc == -EINVAL) {
144 		return -EINVAL;
145 	}
146 
147 	/* update the interface details */
148 	intf = &port_db->ulp_intf_list[ifindex];
149 
150 	intf->type = bnxt_get_interface_type(port_id);
151 	intf->drv_func_id = bnxt_get_fw_func_id(port_id,
152 						BNXT_ULP_INTF_TYPE_INVALID);
153 
154 	func = &port_db->ulp_func_id_tbl[intf->drv_func_id];
155 	if (!func->func_valid) {
156 		func->func_svif = bnxt_get_svif(port_id, true,
157 						BNXT_ULP_INTF_TYPE_INVALID);
158 		func->func_spif = bnxt_get_phy_port_id(port_id);
159 		func->func_parif =
160 			bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
161 		func->func_vnic =
162 			bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_INVALID);
163 		func->phy_port_id = bnxt_get_phy_port_id(port_id);
164 		func->func_valid = true;
165 		func->ifindex = ifindex;
166 	}
167 
168 	if (intf->type == BNXT_ULP_INTF_TYPE_VF_REP) {
169 		intf->vf_func_id =
170 			bnxt_get_fw_func_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
171 
172 		func = &port_db->ulp_func_id_tbl[intf->vf_func_id];
173 		func->func_svif =
174 			bnxt_get_svif(port_id, true, BNXT_ULP_INTF_TYPE_VF_REP);
175 		func->func_spif =
176 			bnxt_get_phy_port_id(port_id);
177 		func->func_parif =
178 			bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
179 		func->func_vnic =
180 			bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
181 		func->phy_port_id = bnxt_get_phy_port_id(port_id);
182 		func->ifindex = ifindex;
183 	}
184 
185 	port_data = &port_db->phy_port_list[func->phy_port_id];
186 	if (!port_data->port_valid) {
187 		port_data->port_svif =
188 			bnxt_get_svif(port_id, false,
189 				      BNXT_ULP_INTF_TYPE_INVALID);
190 		port_data->port_spif = bnxt_get_phy_port_id(port_id);
191 		port_data->port_parif =
192 			bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
193 		port_data->port_vport = bnxt_get_vport(port_id);
194 		port_data->port_valid = true;
195 	}
196 
197 	return 0;
198 }
199 
200 /*
201  * Api to get the ulp ifindex for a given device port.
202  *
203  * ulp_ctxt [in] Ptr to ulp context
204  * port_id [in].device port id
205  * ifindex [out] ulp ifindex
206  *
207  * Returns 0 on success or negative number on failure.
208  */
209 int32_t
210 ulp_port_db_dev_port_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
211 				  uint32_t port_id,
212 				  uint32_t *ifindex)
213 {
214 	struct bnxt_ulp_port_db *port_db;
215 
216 	*ifindex = 0;
217 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
218 	if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
219 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
220 		return -EINVAL;
221 	}
222 	if (!port_db->dev_port_list[port_id])
223 		return -ENOENT;
224 
225 	*ifindex = port_db->dev_port_list[port_id];
226 	return 0;
227 }
228 
229 /*
230  * Api to get the function id for a given ulp ifindex.
231  *
232  * ulp_ctxt [in] Ptr to ulp context
233  * ifindex [in] ulp ifindex
234  * func_id [out] the function id of the given ifindex.
235  *
236  * Returns 0 on success or negative number on failure.
237  */
238 int32_t
239 ulp_port_db_function_id_get(struct bnxt_ulp_context *ulp_ctxt,
240 			    uint32_t ifindex,
241 			    uint32_t fid_type,
242 			    uint16_t *func_id)
243 {
244 	struct bnxt_ulp_port_db *port_db;
245 
246 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
247 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
248 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
249 		return -EINVAL;
250 	}
251 
252 	if (fid_type == BNXT_ULP_DRV_FUNC_FID)
253 		*func_id =  port_db->ulp_intf_list[ifindex].drv_func_id;
254 	else
255 		*func_id =  port_db->ulp_intf_list[ifindex].vf_func_id;
256 
257 	return 0;
258 }
259 
260 /*
261  * Api to get the svif for a given ulp ifindex.
262  *
263  * ulp_ctxt [in] Ptr to ulp context
264  * ifindex [in] ulp ifindex
265  * svif_type [in] the svif type of the given ifindex.
266  * svif [out] the svif of the given ifindex.
267  *
268  * Returns 0 on success or negative number on failure.
269  */
270 int32_t
271 ulp_port_db_svif_get(struct bnxt_ulp_context *ulp_ctxt,
272 		     uint32_t ifindex,
273 		     uint32_t svif_type,
274 		     uint16_t *svif)
275 {
276 	struct bnxt_ulp_port_db *port_db;
277 	uint16_t phy_port_id, func_id;
278 
279 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
280 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
281 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
282 		return -EINVAL;
283 	}
284 
285 	if (svif_type == BNXT_ULP_DRV_FUNC_SVIF) {
286 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
287 		*svif = port_db->ulp_func_id_tbl[func_id].func_svif;
288 	} else if (svif_type == BNXT_ULP_VF_FUNC_SVIF) {
289 		func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
290 		*svif = port_db->ulp_func_id_tbl[func_id].func_svif;
291 	} else {
292 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
293 		phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
294 		*svif = port_db->phy_port_list[phy_port_id].port_svif;
295 	}
296 
297 	return 0;
298 }
299 
300 /*
301  * Api to get the spif for a given ulp ifindex.
302  *
303  * ulp_ctxt [in] Ptr to ulp context
304  * ifindex [in] ulp ifindex
305  * spif_type [in] the spif type of the given ifindex.
306  * spif [out] the spif of the given ifindex.
307  *
308  * Returns 0 on success or negative number on failure.
309  */
310 int32_t
311 ulp_port_db_spif_get(struct bnxt_ulp_context *ulp_ctxt,
312 		     uint32_t ifindex,
313 		     uint32_t spif_type,
314 		     uint16_t *spif)
315 {
316 	struct bnxt_ulp_port_db *port_db;
317 	uint16_t phy_port_id, func_id;
318 
319 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
320 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
321 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
322 		return -EINVAL;
323 	}
324 
325 	if (spif_type == BNXT_ULP_DRV_FUNC_SPIF) {
326 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
327 		*spif = port_db->ulp_func_id_tbl[func_id].func_spif;
328 	} else if (spif_type == BNXT_ULP_VF_FUNC_SPIF) {
329 		func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
330 		*spif = port_db->ulp_func_id_tbl[func_id].func_spif;
331 	} else {
332 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
333 		phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
334 		*spif = port_db->phy_port_list[phy_port_id].port_spif;
335 	}
336 
337 	return 0;
338 }
339 
340 /*
341  * Api to get the parif for a given ulp ifindex.
342  *
343  * ulp_ctxt [in] Ptr to ulp context
344  * ifindex [in] ulp ifindex
345  * parif_type [in] the parif type of the given ifindex.
346  * parif [out] the parif of the given ifindex.
347  *
348  * Returns 0 on success or negative number on failure.
349  */
350 int32_t
351 ulp_port_db_parif_get(struct bnxt_ulp_context *ulp_ctxt,
352 		     uint32_t ifindex,
353 		     uint32_t parif_type,
354 		     uint16_t *parif)
355 {
356 	struct bnxt_ulp_port_db *port_db;
357 	uint16_t phy_port_id, func_id;
358 
359 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
360 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
361 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
362 		return -EINVAL;
363 	}
364 	if (parif_type == BNXT_ULP_DRV_FUNC_PARIF) {
365 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
366 		*parif = port_db->ulp_func_id_tbl[func_id].func_parif;
367 	} else if (parif_type == BNXT_ULP_VF_FUNC_PARIF) {
368 		func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
369 		*parif = port_db->ulp_func_id_tbl[func_id].func_parif;
370 	} else {
371 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
372 		phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
373 		*parif = port_db->phy_port_list[phy_port_id].port_parif;
374 	}
375 	/* Parif needs to be reset to a free partition */
376 	*parif += BNXT_ULP_FREE_PARIF_BASE;
377 
378 	return 0;
379 }
380 
381 /*
382  * Api to get the vnic id for a given ulp ifindex.
383  *
384  * ulp_ctxt [in] Ptr to ulp context
385  * ifindex [in] ulp ifindex
386  * vnic [out] the vnic of the given ifindex.
387  *
388  * Returns 0 on success or negative number on failure.
389  */
390 int32_t
391 ulp_port_db_default_vnic_get(struct bnxt_ulp_context *ulp_ctxt,
392 			     uint32_t ifindex,
393 			     uint32_t vnic_type,
394 			     uint16_t *vnic)
395 {
396 	struct bnxt_ulp_port_db *port_db;
397 	uint16_t func_id;
398 
399 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
400 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
401 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
402 		return -EINVAL;
403 	}
404 
405 	if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) {
406 		func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
407 		*vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
408 	} else {
409 		func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
410 		*vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
411 	}
412 
413 	return 0;
414 }
415 
416 /*
417  * Api to get the vport id for a given ulp ifindex.
418  *
419  * ulp_ctxt [in] Ptr to ulp context
420  * ifindex [in] ulp ifindex
421  * vport [out] the port of the given ifindex.
422  *
423  * Returns 0 on success or negative number on failure.
424  */
425 int32_t
426 ulp_port_db_vport_get(struct bnxt_ulp_context *ulp_ctxt,
427 		      uint32_t ifindex, uint16_t *vport)
428 {
429 	struct bnxt_ulp_port_db *port_db;
430 	uint16_t phy_port_id, func_id;
431 
432 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
433 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
434 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
435 		return -EINVAL;
436 	}
437 
438 	func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
439 	phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
440 	*vport = port_db->phy_port_list[phy_port_id].port_vport;
441 	return 0;
442 }
443 
444 /*
445  * Api to get the vport for a given physical port.
446  *
447  * ulp_ctxt [in] Ptr to ulp context
448  * phy_port [in] physical port index
449  * out_port [out] the port of the given physical index
450  *
451  * Returns 0 on success or negative number on failure.
452  */
453 int32_t
454 ulp_port_db_phy_port_vport_get(struct bnxt_ulp_context *ulp_ctxt,
455 			       uint32_t phy_port,
456 			       uint16_t *out_port)
457 {
458 	struct bnxt_ulp_port_db *port_db;
459 
460 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
461 	if (!port_db || phy_port >= port_db->phy_port_cnt) {
462 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
463 		return -EINVAL;
464 	}
465 	*out_port = port_db->phy_port_list[phy_port].port_vport;
466 	return 0;
467 }
468 
469 /*
470  * Api to get the svif for a given physical port.
471  *
472  * ulp_ctxt [in] Ptr to ulp context
473  * phy_port [in] physical port index
474  * svif [out] the svif of the given physical index
475  *
476  * Returns 0 on success or negative number on failure.
477  */
478 int32_t
479 ulp_port_db_phy_port_svif_get(struct bnxt_ulp_context *ulp_ctxt,
480 			      uint32_t phy_port,
481 			      uint16_t *svif)
482 {
483 	struct bnxt_ulp_port_db *port_db;
484 
485 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
486 	if (!port_db || phy_port >= port_db->phy_port_cnt) {
487 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
488 		return -EINVAL;
489 	}
490 	*svif = port_db->phy_port_list[phy_port].port_svif;
491 	return 0;
492 }
493 
494 /*
495  * Api to get the port type for a given ulp ifindex.
496  *
497  * ulp_ctxt [in] Ptr to ulp context
498  * ifindex [in] ulp ifindex
499  *
500  * Returns port type.
501  */
502 enum bnxt_ulp_intf_type
503 ulp_port_db_port_type_get(struct bnxt_ulp_context *ulp_ctxt,
504 			  uint32_t ifindex)
505 {
506 	struct bnxt_ulp_port_db *port_db;
507 
508 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
509 	if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
510 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
511 		return BNXT_ULP_INTF_TYPE_INVALID;
512 	}
513 	return port_db->ulp_intf_list[ifindex].type;
514 }
515 
516 /*
517  * Api to get the ulp ifindex for a given function id.
518  *
519  * ulp_ctxt [in] Ptr to ulp context
520  * func_id [in].device func id
521  * ifindex [out] ulp ifindex
522  *
523  * Returns 0 on success or negative number on failure.
524  */
525 int32_t
526 ulp_port_db_dev_func_id_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
527 				     uint32_t func_id, uint32_t *ifindex)
528 {
529 	struct bnxt_ulp_port_db *port_db;
530 
531 	*ifindex = 0;
532 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
533 	if (!port_db || func_id >= BNXT_PORT_DB_MAX_FUNC) {
534 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
535 		return -EINVAL;
536 	}
537 	if (!port_db->ulp_func_id_tbl[func_id].func_valid)
538 		return -ENOENT;
539 
540 	*ifindex = port_db->ulp_func_id_tbl[func_id].ifindex;
541 	return 0;
542 }
543 
544 /*
545  * Api to get the function id for a given port id.
546  *
547  * ulp_ctxt [in] Ptr to ulp context
548  * port_id [in] dpdk port id
549  * func_id [out] the function id of the given ifindex.
550  *
551  * Returns 0 on success or negative number on failure.
552  */
553 int32_t
554 ulp_port_db_port_func_id_get(struct bnxt_ulp_context *ulp_ctxt,
555 			     uint16_t port_id, uint16_t *func_id)
556 {
557 	struct bnxt_ulp_port_db *port_db;
558 	uint32_t ifindex;
559 
560 	port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
561 	if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
562 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
563 		return -EINVAL;
564 	}
565 	ifindex = port_db->dev_port_list[port_id];
566 	if (!ifindex)
567 		return -ENOENT;
568 
569 	switch (port_db->ulp_intf_list[ifindex].type) {
570 	case BNXT_ULP_INTF_TYPE_TRUSTED_VF:
571 	case BNXT_ULP_INTF_TYPE_PF:
572 		*func_id =  port_db->ulp_intf_list[ifindex].drv_func_id;
573 		break;
574 	case BNXT_ULP_INTF_TYPE_VF:
575 	case BNXT_ULP_INTF_TYPE_VF_REP:
576 		*func_id =  port_db->ulp_intf_list[ifindex].vf_func_id;
577 		break;
578 	default:
579 		*func_id = 0;
580 		break;
581 	}
582 	return 0;
583 }
584