0fc7c0ab21fefdce09e561a3e0464a70e6aaf2a3
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_port_db.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 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
376         return 0;
377 }
378
379 /*
380  * Api to get the vnic id for a given ulp ifindex.
381  *
382  * ulp_ctxt [in] Ptr to ulp context
383  * ifindex [in] ulp ifindex
384  * vnic [out] the vnic of the given ifindex.
385  *
386  * Returns 0 on success or negative number on failure.
387  */
388 int32_t
389 ulp_port_db_default_vnic_get(struct bnxt_ulp_context *ulp_ctxt,
390                              uint32_t ifindex,
391                              uint32_t vnic_type,
392                              uint16_t *vnic)
393 {
394         struct bnxt_ulp_port_db *port_db;
395         uint16_t func_id;
396
397         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
398         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
399                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
400                 return -EINVAL;
401         }
402
403         if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) {
404                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
405                 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
406         } else {
407                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
408                 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
409         }
410
411         return 0;
412 }
413
414 /*
415  * Api to get the vport id for a given ulp ifindex.
416  *
417  * ulp_ctxt [in] Ptr to ulp context
418  * ifindex [in] ulp ifindex
419  * vport [out] the port of the given ifindex.
420  *
421  * Returns 0 on success or negative number on failure.
422  */
423 int32_t
424 ulp_port_db_vport_get(struct bnxt_ulp_context *ulp_ctxt,
425                       uint32_t ifindex, uint16_t *vport)
426 {
427         struct bnxt_ulp_port_db *port_db;
428         uint16_t phy_port_id, func_id;
429
430         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
431         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
432                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
433                 return -EINVAL;
434         }
435
436         func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
437         phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
438         *vport = port_db->phy_port_list[phy_port_id].port_vport;
439         return 0;
440 }
441
442 /*
443  * Api to get the vport for a given physical port.
444  *
445  * ulp_ctxt [in] Ptr to ulp context
446  * phy_port [in] physical port index
447  * out_port [out] the port of the given physical index
448  *
449  * Returns 0 on success or negative number on failure.
450  */
451 int32_t
452 ulp_port_db_phy_port_vport_get(struct bnxt_ulp_context *ulp_ctxt,
453                                uint32_t phy_port,
454                                uint16_t *out_port)
455 {
456         struct bnxt_ulp_port_db *port_db;
457
458         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
459         if (!port_db || phy_port >= port_db->phy_port_cnt) {
460                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
461                 return -EINVAL;
462         }
463         *out_port = port_db->phy_port_list[phy_port].port_vport;
464         return 0;
465 }
466
467 /*
468  * Api to get the svif for a given physical port.
469  *
470  * ulp_ctxt [in] Ptr to ulp context
471  * phy_port [in] physical port index
472  * svif [out] the svif of the given physical index
473  *
474  * Returns 0 on success or negative number on failure.
475  */
476 int32_t
477 ulp_port_db_phy_port_svif_get(struct bnxt_ulp_context *ulp_ctxt,
478                               uint32_t phy_port,
479                               uint16_t *svif)
480 {
481         struct bnxt_ulp_port_db *port_db;
482
483         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
484         if (!port_db || phy_port >= port_db->phy_port_cnt) {
485                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
486                 return -EINVAL;
487         }
488         *svif = port_db->phy_port_list[phy_port].port_svif;
489         return 0;
490 }
491
492 /*
493  * Api to get the port type for a given ulp ifindex.
494  *
495  * ulp_ctxt [in] Ptr to ulp context
496  * ifindex [in] ulp ifindex
497  *
498  * Returns port type.
499  */
500 enum bnxt_ulp_intf_type
501 ulp_port_db_port_type_get(struct bnxt_ulp_context *ulp_ctxt,
502                           uint32_t ifindex)
503 {
504         struct bnxt_ulp_port_db *port_db;
505
506         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
507         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
508                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
509                 return BNXT_ULP_INTF_TYPE_INVALID;
510         }
511         return port_db->ulp_intf_list[ifindex].type;
512 }
513
514 /*
515  * Api to get the ulp ifindex for a given function id.
516  *
517  * ulp_ctxt [in] Ptr to ulp context
518  * func_id [in].device func id
519  * ifindex [out] ulp ifindex
520  *
521  * Returns 0 on success or negative number on failure.
522  */
523 int32_t
524 ulp_port_db_dev_func_id_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
525                                      uint32_t func_id, uint32_t *ifindex)
526 {
527         struct bnxt_ulp_port_db *port_db;
528
529         *ifindex = 0;
530         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
531         if (!port_db || func_id >= BNXT_PORT_DB_MAX_FUNC) {
532                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
533                 return -EINVAL;
534         }
535         if (!port_db->ulp_func_id_tbl[func_id].func_valid)
536                 return -ENOENT;
537
538         *ifindex = port_db->ulp_func_id_tbl[func_id].ifindex;
539         return 0;
540 }