net/bnxt: enhance port DB
[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
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         }
166
167         if (intf->type == BNXT_ULP_INTF_TYPE_VF_REP) {
168                 intf->vf_func_id =
169                         bnxt_get_fw_func_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
170
171                 func = &port_db->ulp_func_id_tbl[intf->vf_func_id];
172                 func->func_svif =
173                         bnxt_get_svif(port_id, true, BNXT_ULP_INTF_TYPE_VF_REP);
174                 func->func_spif =
175                         bnxt_get_phy_port_id(port_id);
176                 func->func_parif =
177                         bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
178                 func->func_vnic =
179                         bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
180                 func->phy_port_id = bnxt_get_phy_port_id(port_id);
181         }
182
183         port_data = &port_db->phy_port_list[func->phy_port_id];
184         if (!port_data->port_valid) {
185                 port_data->port_svif =
186                         bnxt_get_svif(port_id, false,
187                                       BNXT_ULP_INTF_TYPE_INVALID);
188                 port_data->port_spif = bnxt_get_phy_port_id(port_id);
189                 port_data->port_parif =
190                         bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
191                 port_data->port_vport = bnxt_get_vport(port_id);
192                 port_data->port_valid = true;
193         }
194
195         return 0;
196 }
197
198 /*
199  * Api to get the ulp ifindex for a given device port.
200  *
201  * ulp_ctxt [in] Ptr to ulp context
202  * port_id [in].device port id
203  * ifindex [out] ulp ifindex
204  *
205  * Returns 0 on success or negative number on failure.
206  */
207 int32_t
208 ulp_port_db_dev_port_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
209                                   uint32_t port_id,
210                                   uint32_t *ifindex)
211 {
212         struct bnxt_ulp_port_db *port_db;
213
214         *ifindex = 0;
215         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
216         if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
217                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
218                 return -EINVAL;
219         }
220         if (!port_db->dev_port_list[port_id])
221                 return -ENOENT;
222
223         *ifindex = port_db->dev_port_list[port_id];
224         return 0;
225 }
226
227 /*
228  * Api to get the function id for a given ulp ifindex.
229  *
230  * ulp_ctxt [in] Ptr to ulp context
231  * ifindex [in] ulp ifindex
232  * func_id [out] the function id of the given ifindex.
233  *
234  * Returns 0 on success or negative number on failure.
235  */
236 int32_t
237 ulp_port_db_function_id_get(struct bnxt_ulp_context *ulp_ctxt,
238                             uint32_t ifindex,
239                             uint32_t fid_type,
240                             uint16_t *func_id)
241 {
242         struct bnxt_ulp_port_db *port_db;
243
244         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
245         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
246                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
247                 return -EINVAL;
248         }
249
250         if (fid_type == BNXT_ULP_DRV_FUNC_FID)
251                 *func_id =  port_db->ulp_intf_list[ifindex].drv_func_id;
252         else
253                 *func_id =  port_db->ulp_intf_list[ifindex].vf_func_id;
254
255         return 0;
256 }
257
258 /*
259  * Api to get the svif for a given ulp ifindex.
260  *
261  * ulp_ctxt [in] Ptr to ulp context
262  * ifindex [in] ulp ifindex
263  * svif_type [in] the svif type of the given ifindex.
264  * svif [out] the svif of the given ifindex.
265  *
266  * Returns 0 on success or negative number on failure.
267  */
268 int32_t
269 ulp_port_db_svif_get(struct bnxt_ulp_context *ulp_ctxt,
270                      uint32_t ifindex,
271                      uint32_t svif_type,
272                      uint16_t *svif)
273 {
274         struct bnxt_ulp_port_db *port_db;
275         uint16_t phy_port_id, func_id;
276
277         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
278         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
279                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
280                 return -EINVAL;
281         }
282
283         if (svif_type == BNXT_ULP_DRV_FUNC_SVIF) {
284                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
285                 *svif = port_db->ulp_func_id_tbl[func_id].func_svif;
286         } else if (svif_type == BNXT_ULP_VF_FUNC_SVIF) {
287                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
288                 *svif = port_db->ulp_func_id_tbl[func_id].func_svif;
289         } else {
290                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
291                 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
292                 *svif = port_db->phy_port_list[phy_port_id].port_svif;
293         }
294
295         return 0;
296 }
297
298 /*
299  * Api to get the spif for a given ulp ifindex.
300  *
301  * ulp_ctxt [in] Ptr to ulp context
302  * ifindex [in] ulp ifindex
303  * spif_type [in] the spif type of the given ifindex.
304  * spif [out] the spif of the given ifindex.
305  *
306  * Returns 0 on success or negative number on failure.
307  */
308 int32_t
309 ulp_port_db_spif_get(struct bnxt_ulp_context *ulp_ctxt,
310                      uint32_t ifindex,
311                      uint32_t spif_type,
312                      uint16_t *spif)
313 {
314         struct bnxt_ulp_port_db *port_db;
315         uint16_t phy_port_id, func_id;
316
317         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
318         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
319                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
320                 return -EINVAL;
321         }
322
323         if (spif_type == BNXT_ULP_DRV_FUNC_SPIF) {
324                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
325                 *spif = port_db->ulp_func_id_tbl[func_id].func_spif;
326         } else if (spif_type == BNXT_ULP_VF_FUNC_SPIF) {
327                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
328                 *spif = port_db->ulp_func_id_tbl[func_id].func_spif;
329         } else {
330                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
331                 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
332                 *spif = port_db->phy_port_list[phy_port_id].port_spif;
333         }
334
335         return 0;
336 }
337
338 /*
339  * Api to get the parif for a given ulp ifindex.
340  *
341  * ulp_ctxt [in] Ptr to ulp context
342  * ifindex [in] ulp ifindex
343  * parif_type [in] the parif type of the given ifindex.
344  * parif [out] the parif of the given ifindex.
345  *
346  * Returns 0 on success or negative number on failure.
347  */
348 int32_t
349 ulp_port_db_parif_get(struct bnxt_ulp_context *ulp_ctxt,
350                      uint32_t ifindex,
351                      uint32_t parif_type,
352                      uint16_t *parif)
353 {
354         struct bnxt_ulp_port_db *port_db;
355         uint16_t phy_port_id, func_id;
356
357         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
358         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
359                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
360                 return -EINVAL;
361         }
362         if (parif_type == BNXT_ULP_DRV_FUNC_PARIF) {
363                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
364                 *parif = port_db->ulp_func_id_tbl[func_id].func_parif;
365         } else if (parif_type == BNXT_ULP_VF_FUNC_PARIF) {
366                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
367                 *parif = port_db->ulp_func_id_tbl[func_id].func_parif;
368         } else {
369                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
370                 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
371                 *parif = port_db->phy_port_list[phy_port_id].port_parif;
372         }
373
374         return 0;
375 }
376
377 /*
378  * Api to get the vnic id for a given ulp ifindex.
379  *
380  * ulp_ctxt [in] Ptr to ulp context
381  * ifindex [in] ulp ifindex
382  * vnic [out] the vnic of the given ifindex.
383  *
384  * Returns 0 on success or negative number on failure.
385  */
386 int32_t
387 ulp_port_db_default_vnic_get(struct bnxt_ulp_context *ulp_ctxt,
388                              uint32_t ifindex,
389                              uint32_t vnic_type,
390                              uint16_t *vnic)
391 {
392         struct bnxt_ulp_port_db *port_db;
393         uint16_t func_id;
394
395         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
396         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
397                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
398                 return -EINVAL;
399         }
400
401         if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) {
402                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
403                 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
404         } else {
405                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
406                 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
407         }
408
409         return 0;
410 }
411
412 /*
413  * Api to get the vport id for a given ulp ifindex.
414  *
415  * ulp_ctxt [in] Ptr to ulp context
416  * ifindex [in] ulp ifindex
417  * vport [out] the port of the given ifindex.
418  *
419  * Returns 0 on success or negative number on failure.
420  */
421 int32_t
422 ulp_port_db_vport_get(struct bnxt_ulp_context *ulp_ctxt,
423                       uint32_t ifindex, uint16_t *vport)
424 {
425         struct bnxt_ulp_port_db *port_db;
426         uint16_t phy_port_id, func_id;
427
428         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
429         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
430                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
431                 return -EINVAL;
432         }
433
434         func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
435         phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
436         *vport = port_db->phy_port_list[phy_port_id].port_vport;
437         return 0;
438 }