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