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