net/bnxt: support shared session
[dpdk.git] / drivers / net / bnxt / tf_core / tf_device.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include "tf_device.h"
7 #include "tf_device_p4.h"
8 #include "tf_device_p58.h"
9 #include "tfp.h"
10 #include "tf_em.h"
11 #include "tf_rm.h"
12
13 struct tf;
14
15 /* Forward declarations */
16 static int tf_dev_unbind_p4(struct tf *tfp);
17 static int tf_dev_unbind_p58(struct tf *tfp);
18
19 /**
20  * Resource Reservation Check function
21  *
22  * [in] count
23  *   Number of module subtypes
24  *
25  * [in] cfg
26  *   Pointer to rm element config
27  *
28  * [in] reservations
29  *   Pointer to resource reservation array
30  *
31  * Returns
32  *   - (n) number of tables in module that have non-zero reservation count.
33  */
34 static int
35 tf_dev_reservation_check(uint16_t count,
36                          struct tf_rm_element_cfg *cfg,
37                          uint16_t *reservations)
38 {
39         uint16_t cnt = 0;
40         uint16_t *rm_num;
41         int i, j;
42
43         for (i = 0; i < TF_DIR_MAX; i++) {
44                 rm_num = (uint16_t *)reservations + i * count;
45                 for (j = 0; j < count; j++) {
46                         if ((cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
47                              cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) &&
48                              rm_num[j] > 0)
49                                 cnt++;
50                 }
51         }
52
53         return cnt;
54 }
55
56 /**
57  * Device specific bind function, WH+
58  *
59  * [in] tfp
60  *   Pointer to TF handle
61  *
62  * [in] shadow_copy
63  *   Flag controlling shadow copy DB creation
64  *
65  * [in] resources
66  *   Pointer to resource allocation information
67  *
68  * [out] dev_handle
69  *   Device handle
70  *
71  * Returns
72  *   - (0) if successful.
73  *   - (-EINVAL) on parameter or internal failure.
74  */
75 static int
76 tf_dev_bind_p4(struct tf *tfp,
77                bool shadow_copy,
78                struct tf_session_resources *resources,
79                struct tf_dev_info *dev_handle)
80 {
81         int rc;
82         int frc;
83         int rsv_cnt;
84         bool no_rsv_flag = true;
85         struct tf_ident_cfg_parms ident_cfg;
86         struct tf_tbl_cfg_parms tbl_cfg;
87         struct tf_tcam_cfg_parms tcam_cfg;
88         struct tf_em_cfg_parms em_cfg;
89         struct tf_if_tbl_cfg_parms if_tbl_cfg;
90         struct tf_global_cfg_cfg_parms global_cfg;
91
92         /* Initial function initialization */
93         dev_handle->ops = &tf_dev_ops_p4_init;
94
95         /* Initialize the modules */
96
97         rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
98                                            tf_ident_p4,
99                                            (uint16_t *)resources->ident_cnt);
100         if (rsv_cnt) {
101                 ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
102                 ident_cfg.cfg = tf_ident_p4;
103                 ident_cfg.shadow_copy = shadow_copy;
104                 ident_cfg.resources = resources;
105                 rc = tf_ident_bind(tfp, &ident_cfg);
106                 if (rc) {
107                         TFP_DRV_LOG(ERR,
108                                     "Identifier initialization failure\n");
109                         goto fail;
110                 }
111
112                 no_rsv_flag = false;
113         }
114
115         rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
116                                            tf_tbl_p4,
117                                            (uint16_t *)resources->tbl_cnt);
118         if (rsv_cnt) {
119                 tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
120                 tbl_cfg.cfg = tf_tbl_p4;
121                 tbl_cfg.shadow_copy = shadow_copy;
122                 tbl_cfg.resources = resources;
123                 rc = tf_tbl_bind(tfp, &tbl_cfg);
124                 if (rc) {
125                         TFP_DRV_LOG(ERR,
126                                     "Table initialization failure\n");
127                         goto fail;
128                 }
129
130                 no_rsv_flag = false;
131         }
132
133         rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
134                                            tf_tcam_p4,
135                                            (uint16_t *)resources->tcam_cnt);
136         if (rsv_cnt) {
137                 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
138                 tcam_cfg.cfg = tf_tcam_p4;
139                 tcam_cfg.shadow_copy = shadow_copy;
140                 tcam_cfg.resources = resources;
141                 rc = tf_tcam_bind(tfp, &tcam_cfg);
142                 if (rc) {
143                         TFP_DRV_LOG(ERR,
144                                     "TCAM initialization failure\n");
145                         goto fail;
146                 }
147                 no_rsv_flag = false;
148         }
149
150         /*
151          * EEM
152          */
153
154         em_cfg.cfg = tf_em_ext_p4;
155         rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
156                                            em_cfg.cfg,
157                                            (uint16_t *)resources->em_cnt);
158         if (rsv_cnt) {
159                 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
160                 em_cfg.resources = resources;
161                 em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST;
162                 rc = tf_em_ext_common_bind(tfp, &em_cfg);
163                 if (rc) {
164                         TFP_DRV_LOG(ERR,
165                                     "EEM initialization failure\n");
166                         goto fail;
167                 }
168                 no_rsv_flag = false;
169         }
170
171         /*
172          * EM
173          */
174         rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
175                                            tf_em_int_p4,
176                                            (uint16_t *)resources->em_cnt);
177         if (rsv_cnt) {
178                 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
179                 em_cfg.cfg = tf_em_int_p4;
180                 em_cfg.resources = resources;
181                 em_cfg.mem_type = 0; /* Not used by EM */
182
183                 rc = tf_em_int_bind(tfp, &em_cfg);
184                 if (rc) {
185                         TFP_DRV_LOG(ERR,
186                                     "EM initialization failure\n");
187                         goto fail;
188                 }
189                 no_rsv_flag = false;
190         }
191
192         /*
193          * There is no rm reserved for any tables
194          *
195          */
196         if (no_rsv_flag) {
197                 TFP_DRV_LOG(ERR,
198                             "No rm reserved for any tables\n");
199                 return -ENOMEM;
200         }
201
202         /*
203          * IF_TBL
204          */
205         if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
206         if_tbl_cfg.cfg = tf_if_tbl_p4;
207         if_tbl_cfg.shadow_copy = shadow_copy;
208         rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
209         if (rc) {
210                 TFP_DRV_LOG(ERR,
211                             "IF Table initialization failure\n");
212                 goto fail;
213         }
214
215         /*
216          * GLOBAL_CFG
217          */
218         global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
219         global_cfg.cfg = tf_global_cfg_p4;
220         rc = tf_global_cfg_bind(tfp, &global_cfg);
221         if (rc) {
222                 TFP_DRV_LOG(ERR,
223                             "Global Cfg initialization failure\n");
224                 goto fail;
225         }
226
227         /* Final function initialization */
228         dev_handle->ops = &tf_dev_ops_p4;
229
230         return 0;
231
232  fail:
233         /* Cleanup of already created modules */
234         frc = tf_dev_unbind_p4(tfp);
235         if (frc)
236                 return frc;
237
238         return rc;
239 }
240
241 /**
242  * Device specific unbind function, WH+
243  *
244  * [in] tfp
245  *   Pointer to TF handle
246  *
247  * Returns
248  *   - (0) if successful.
249  *   - (-EINVAL) on failure.
250  */
251 static int
252 tf_dev_unbind_p4(struct tf *tfp)
253 {
254         int rc = 0;
255         bool fail = false;
256
257         /* Unbind all the support modules. As this is only done on
258          * close we only report errors as everything has to be cleaned
259          * up regardless.
260          *
261          * In case of residuals TCAMs are cleaned up first as to
262          * invalidate the pipeline in a clean manner.
263          */
264         rc = tf_tcam_unbind(tfp);
265         if (rc) {
266                 TFP_DRV_LOG(ERR,
267                             "Device unbind failed, TCAM\n");
268                 fail = true;
269         }
270
271         rc = tf_ident_unbind(tfp);
272         if (rc) {
273                 TFP_DRV_LOG(ERR,
274                             "Device unbind failed, Identifier\n");
275                 fail = true;
276         }
277
278         rc = tf_tbl_unbind(tfp);
279         if (rc) {
280                 TFP_DRV_LOG(ERR,
281                             "Device unbind failed, Table Type\n");
282                 fail = true;
283         }
284
285         rc = tf_em_ext_common_unbind(tfp);
286         if (rc) {
287                 TFP_DRV_LOG(ERR,
288                             "Device unbind failed, EEM\n");
289                 fail = true;
290         }
291
292         rc = tf_em_int_unbind(tfp);
293         if (rc) {
294                 TFP_DRV_LOG(ERR,
295                             "Device unbind failed, EM\n");
296                 fail = true;
297         }
298
299         rc = tf_if_tbl_unbind(tfp);
300         if (rc) {
301                 TFP_DRV_LOG(ERR,
302                             "Device unbind failed, IF Table Type\n");
303                 fail = true;
304         }
305
306         rc = tf_global_cfg_unbind(tfp);
307         if (rc) {
308                 TFP_DRV_LOG(ERR,
309                             "Device unbind failed, Global Cfg Type\n");
310                 fail = true;
311         }
312
313         if (fail)
314                 return -1;
315
316         return rc;
317 }
318
319 /**
320  * Device specific bind function, THOR
321  *
322  * [in] tfp
323  *   Pointer to TF handle
324  *
325  * [in] shadow_copy
326  *   Flag controlling shadow copy DB creation
327  *
328  * [in] resources
329  *   Pointer to resource allocation information
330  *
331  * [out] dev_handle
332  *   Device handle
333  *
334  * Returns
335  *   - (0) if successful.
336  *   - (-EINVAL) on parameter or internal failure.
337  */
338 static int
339 tf_dev_bind_p58(struct tf *tfp,
340                 bool shadow_copy,
341                 struct tf_session_resources *resources,
342                 struct tf_dev_info *dev_handle)
343 {
344         int rc;
345         int frc;
346         int rsv_cnt;
347         bool no_rsv_flag = true;
348         struct tf_ident_cfg_parms ident_cfg;
349         struct tf_tbl_cfg_parms tbl_cfg;
350         struct tf_tcam_cfg_parms tcam_cfg;
351         struct tf_em_cfg_parms em_cfg;
352         struct tf_if_tbl_cfg_parms if_tbl_cfg;
353         struct tf_global_cfg_cfg_parms global_cfg;
354         struct tf_session *tfs;
355
356         /* Initial function initialization */
357         dev_handle->ops = &tf_dev_ops_p58_init;
358
359         /* Retrieve the session information */
360         rc = tf_session_get_session_internal(tfp, &tfs);
361         if (rc)
362                 return rc;
363
364         rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX,
365                                            tf_ident_p58,
366                                            (uint16_t *)resources->ident_cnt);
367         if (rsv_cnt) {
368                 ident_cfg.num_elements = TF_IDENT_TYPE_MAX;
369                 ident_cfg.cfg = tf_ident_p58;
370                 ident_cfg.shadow_copy = shadow_copy;
371                 ident_cfg.resources = resources;
372                 rc = tf_ident_bind(tfp, &ident_cfg);
373                 if (rc) {
374                         TFP_DRV_LOG(ERR,
375                                     "Identifier initialization failure\n");
376                         goto fail;
377                 }
378                 no_rsv_flag = false;
379         }
380
381         rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX,
382                                            tf_tbl_p58,
383                                            (uint16_t *)resources->tbl_cnt);
384         if (rsv_cnt) {
385                 tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
386                 tbl_cfg.cfg = tf_tbl_p58;
387                 tbl_cfg.shadow_copy = shadow_copy;
388                 tbl_cfg.resources = resources;
389                 rc = tf_tbl_bind(tfp, &tbl_cfg);
390                 if (rc) {
391                         TFP_DRV_LOG(ERR,
392                                     "Table initialization failure\n");
393                         goto fail;
394                 }
395                 no_rsv_flag = false;
396         }
397
398         rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
399                                            tf_tcam_p58,
400                                            (uint16_t *)resources->tcam_cnt);
401         if (rsv_cnt) {
402                 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX;
403                 tcam_cfg.cfg = tf_tcam_p58;
404                 tcam_cfg.shadow_copy = shadow_copy;
405                 tcam_cfg.resources = resources;
406                 rc = tf_tcam_bind(tfp, &tcam_cfg);
407                 if (rc) {
408                         TFP_DRV_LOG(ERR,
409                                     "TCAM initialization failure\n");
410                         goto fail;
411                 }
412                 no_rsv_flag = false;
413         }
414
415         /*
416          * EM
417          */
418         rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX,
419                                            tf_em_int_p58,
420                                            (uint16_t *)resources->em_cnt);
421         if (rsv_cnt) {
422                 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX;
423                 em_cfg.cfg = tf_em_int_p58;
424                 em_cfg.resources = resources;
425                 em_cfg.mem_type = 0; /* Not used by EM */
426
427                 rc = tf_em_int_bind(tfp, &em_cfg);
428                 if (rc) {
429                         TFP_DRV_LOG(ERR,
430                                     "EM initialization failure\n");
431                         goto fail;
432                 }
433                 no_rsv_flag = false;
434         }
435
436         /*
437          * There is no rm reserved for any tables
438          *
439          */
440         if (no_rsv_flag) {
441                 TFP_DRV_LOG(ERR,
442                             "No rm reserved for any tables\n");
443                 return -ENOMEM;
444         }
445
446         /*
447          * IF_TBL
448          */
449         if (!tf_session_is_shared_session(tfs)) {
450                 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX;
451                 if_tbl_cfg.cfg = tf_if_tbl_p58;
452                 if_tbl_cfg.shadow_copy = shadow_copy;
453                 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg);
454                 if (rc) {
455                         TFP_DRV_LOG(ERR,
456                                     "IF Table initialization failure\n");
457                         goto fail;
458                 }
459
460                 /*
461                  * GLOBAL_CFG
462                  */
463                 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX;
464                 global_cfg.cfg = tf_global_cfg_p58;
465                 rc = tf_global_cfg_bind(tfp, &global_cfg);
466                 if (rc) {
467                         TFP_DRV_LOG(ERR,
468                                     "Global Cfg initialization failure\n");
469                         goto fail;
470                 }
471         }
472
473         /* Final function initialization */
474         dev_handle->ops = &tf_dev_ops_p58;
475
476         return 0;
477
478  fail:
479         /* Cleanup of already created modules */
480         frc = tf_dev_unbind_p58(tfp);
481         if (frc)
482                 return frc;
483
484         return rc;
485 }
486
487 /**
488  * Device specific unbind function, THOR
489  *
490  * [in] tfp
491  *   Pointer to TF handle
492  *
493  * Returns
494  *   - (0) if successful.
495  *   - (-EINVAL) on failure.
496  */
497 static int
498 tf_dev_unbind_p58(struct tf *tfp)
499 {
500         int rc = 0;
501         bool fail = false;
502         struct tf_session *tfs;
503
504         /* Retrieve the session information */
505         rc = tf_session_get_session_internal(tfp, &tfs);
506         if (rc)
507                 return rc;
508
509         /* Unbind all the support modules. As this is only done on
510          * close we only report errors as everything has to be cleaned
511          * up regardless.
512          *
513          * In case of residuals TCAMs are cleaned up first as to
514          * invalidate the pipeline in a clean manner.
515          */
516         rc = tf_tcam_unbind(tfp);
517         if (rc) {
518                 TFP_DRV_LOG(ERR,
519                             "Device unbind failed, TCAM\n");
520                 fail = true;
521         }
522
523         rc = tf_ident_unbind(tfp);
524         if (rc) {
525                 TFP_DRV_LOG(ERR,
526                             "Device unbind failed, Identifier\n");
527                 fail = true;
528         }
529
530         rc = tf_tbl_unbind(tfp);
531         if (rc) {
532                 TFP_DRV_LOG(ERR,
533                             "Device unbind failed, Table Type\n");
534                 fail = true;
535         }
536
537         rc = tf_em_int_unbind(tfp);
538         if (rc) {
539                 TFP_DRV_LOG(ERR,
540                             "Device unbind failed, EM\n");
541                 fail = true;
542         }
543
544         if (!tf_session_is_shared_session(tfs)) {
545                 rc = tf_if_tbl_unbind(tfp);
546                 if (rc) {
547                         TFP_DRV_LOG(ERR,
548                                     "Device unbind failed, IF Table Type\n");
549                         fail = true;
550                 }
551
552                 rc = tf_global_cfg_unbind(tfp);
553                 if (rc) {
554                         TFP_DRV_LOG(ERR,
555                                     "Device unbind failed, Global Cfg Type\n");
556                         fail = true;
557                 }
558         }
559
560         if (fail)
561                 return -1;
562
563         return rc;
564 }
565
566 int
567 tf_dev_bind(struct tf *tfp __rte_unused,
568             enum tf_device_type type,
569             bool shadow_copy,
570             struct tf_session_resources *resources,
571             struct tf_dev_info *dev_handle)
572 {
573         switch (type) {
574         case TF_DEVICE_TYPE_WH:
575         case TF_DEVICE_TYPE_SR:
576                 dev_handle->type = type;
577                 return tf_dev_bind_p4(tfp,
578                                       shadow_copy,
579                                       resources,
580                                       dev_handle);
581         case TF_DEVICE_TYPE_THOR:
582                 dev_handle->type = type;
583                 return tf_dev_bind_p58(tfp,
584                                        shadow_copy,
585                                        resources,
586                                        dev_handle);
587         default:
588                 TFP_DRV_LOG(ERR,
589                             "No such device\n");
590                 return -ENODEV;
591         }
592 }
593
594 int
595 tf_dev_bind_ops(enum tf_device_type type,
596                 struct tf_dev_info *dev_handle)
597 {
598         switch (type) {
599         case TF_DEVICE_TYPE_WH:
600         case TF_DEVICE_TYPE_SR:
601                 dev_handle->ops = &tf_dev_ops_p4_init;
602                 break;
603         case TF_DEVICE_TYPE_THOR:
604                 dev_handle->ops = &tf_dev_ops_p58_init;
605                 break;
606         default:
607                 TFP_DRV_LOG(ERR,
608                             "No such device\n");
609                 return -ENODEV;
610         }
611
612         return 0;
613 }
614
615 int
616 tf_dev_unbind(struct tf *tfp,
617               struct tf_dev_info *dev_handle)
618 {
619         switch (dev_handle->type) {
620         case TF_DEVICE_TYPE_WH:
621         case TF_DEVICE_TYPE_SR:
622                 return tf_dev_unbind_p4(tfp);
623         case TF_DEVICE_TYPE_THOR:
624                 return tf_dev_unbind_p58(tfp);
625         default:
626                 TFP_DRV_LOG(ERR,
627                             "No such device\n");
628                 return -ENODEV;
629         }
630 }