net/bnxt: support TruFlow core table scope
[dpdk.git] / drivers / net / bnxt / tf_core / tf_core.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <stdio.h>
7
8 #include "tf_core.h"
9 #include "tf_session.h"
10 #include "tf_tbl.h"
11 #include "tf_rm.h"
12 #include "tf_msg.h"
13 #include "tfp.h"
14 #include "bitalloc.h"
15 #include "bnxt.h"
16 #include "rand.h"
17
18 static inline uint32_t SWAP_WORDS32(uint32_t val32)
19 {
20         return (((val32 & 0x0000ffff) << 16) |
21                 ((val32 & 0xffff0000) >> 16));
22 }
23
24 static void tf_seeds_init(struct tf_session *session)
25 {
26         int i;
27         uint32_t r;
28
29         /* Initialize the lfsr */
30         rand_init();
31
32         /* RX and TX use the same seed values */
33         session->lkup_lkup3_init_cfg[TF_DIR_RX] =
34                 session->lkup_lkup3_init_cfg[TF_DIR_TX] =
35                                                 SWAP_WORDS32(rand32());
36
37         for (i = 0; i < TF_LKUP_SEED_MEM_SIZE / 2; i++) {
38                 r = SWAP_WORDS32(rand32());
39                 session->lkup_em_seed_mem[TF_DIR_RX][i * 2] = r;
40                 session->lkup_em_seed_mem[TF_DIR_TX][i * 2] = r;
41                 r = SWAP_WORDS32(rand32());
42                 session->lkup_em_seed_mem[TF_DIR_RX][i * 2 + 1] = (r & 0x1);
43                 session->lkup_em_seed_mem[TF_DIR_TX][i * 2 + 1] = (r & 0x1);
44         }
45 }
46
47 int
48 tf_open_session(struct tf                    *tfp,
49                 struct tf_open_session_parms *parms)
50 {
51         int rc;
52         struct tf_session *session;
53         struct tfp_calloc_parms alloc_parms;
54         unsigned int domain, bus, slot, device;
55         uint8_t fw_session_id;
56
57         if (tfp == NULL || parms == NULL)
58                 return -EINVAL;
59
60         /* Filter out any non-supported device types on the Core
61          * side. It is assumed that the Firmware will be supported if
62          * firmware open session succeeds.
63          */
64         if (parms->device_type != TF_DEVICE_TYPE_WH)
65                 return -ENOTSUP;
66
67         /* Build the beginning of session_id */
68         rc = sscanf(parms->ctrl_chan_name,
69                     "%x:%x:%x.%d",
70                     &domain,
71                     &bus,
72                     &slot,
73                     &device);
74         if (rc != 4) {
75                 PMD_DRV_LOG(ERR,
76                             "Failed to scan device ctrl_chan_name\n");
77                 return -EINVAL;
78         }
79
80         /* open FW session and get a new session_id */
81         rc = tf_msg_session_open(tfp,
82                                  parms->ctrl_chan_name,
83                                  &fw_session_id);
84         if (rc) {
85                 /* Log error */
86                 if (rc == -EEXIST)
87                         PMD_DRV_LOG(ERR,
88                                     "Session is already open, rc:%d\n",
89                                     rc);
90                 else
91                         PMD_DRV_LOG(ERR,
92                                     "Open message send failed, rc:%d\n",
93                                     rc);
94
95                 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
96                 return rc;
97         }
98
99         /* Allocate session */
100         alloc_parms.nitems = 1;
101         alloc_parms.size = sizeof(struct tf_session_info);
102         alloc_parms.alignment = 0;
103         rc = tfp_calloc(&alloc_parms);
104         if (rc) {
105                 /* Log error */
106                 PMD_DRV_LOG(ERR,
107                             "Failed to allocate session info, rc:%d\n",
108                             rc);
109                 goto cleanup;
110         }
111
112         tfp->session = (struct tf_session_info *)alloc_parms.mem_va;
113
114         /* Allocate core data for the session */
115         alloc_parms.nitems = 1;
116         alloc_parms.size = sizeof(struct tf_session);
117         alloc_parms.alignment = 0;
118         rc = tfp_calloc(&alloc_parms);
119         if (rc) {
120                 /* Log error */
121                 PMD_DRV_LOG(ERR,
122                             "Failed to allocate session data, rc:%d\n",
123                             rc);
124                 goto cleanup;
125         }
126
127         tfp->session->core_data = alloc_parms.mem_va;
128
129         session = (struct tf_session *)tfp->session->core_data;
130         tfp_memcpy(session->ctrl_chan_name,
131                    parms->ctrl_chan_name,
132                    TF_SESSION_NAME_MAX);
133
134         /* Initialize Session */
135         session->device_type = parms->device_type;
136         tf_rm_init(tfp);
137
138         /* Construct the Session ID */
139         session->session_id.internal.domain = domain;
140         session->session_id.internal.bus = bus;
141         session->session_id.internal.device = device;
142         session->session_id.internal.fw_session_id = fw_session_id;
143
144         rc = tf_msg_session_qcfg(tfp);
145         if (rc) {
146                 /* Log error */
147                 PMD_DRV_LOG(ERR,
148                             "Query config message send failed, rc:%d\n",
149                             rc);
150                 goto cleanup_close;
151         }
152
153         /* Shadow DB configuration */
154         if (parms->shadow_copy) {
155                 /* Ignore shadow_copy setting */
156                 session->shadow_copy = 0;/* parms->shadow_copy; */
157 #if (TF_SHADOW == 1)
158                 rc = tf_rm_shadow_db_init(tfs);
159                 if (rc)
160                         PMD_DRV_LOG(ERR,
161                                     "Shadow DB Initialization failed\n, rc:%d",
162                                     rc);
163                 /* Add additional processing */
164 #endif /* TF_SHADOW */
165         }
166
167         /* Adjust the Session with what firmware allowed us to get */
168         rc = tf_rm_allocate_validate(tfp);
169         if (rc) {
170                 /* Log error */
171                 goto cleanup_close;
172         }
173
174         /* Setup hash seeds */
175         tf_seeds_init(session);
176
177         /* Initialize external pool data structures */
178         tf_init_tbl_pool(session);
179
180         session->ref_count++;
181
182         /* Return session ID */
183         parms->session_id = session->session_id;
184
185         PMD_DRV_LOG(INFO,
186                     "Session created, session_id:%d\n",
187                     parms->session_id.id);
188
189         PMD_DRV_LOG(INFO,
190                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
191                     parms->session_id.internal.domain,
192                     parms->session_id.internal.bus,
193                     parms->session_id.internal.device,
194                     parms->session_id.internal.fw_session_id);
195
196         return 0;
197
198  cleanup:
199         tfp_free(tfp->session->core_data);
200         tfp_free(tfp->session);
201         tfp->session = NULL;
202         return rc;
203
204  cleanup_close:
205         tf_close_session(tfp);
206         return -EINVAL;
207 }
208
209 int
210 tf_attach_session(struct tf *tfp __rte_unused,
211                   struct tf_attach_session_parms *parms __rte_unused)
212 {
213 #if (TF_SHARED == 1)
214         int rc;
215
216         if (tfp == NULL)
217                 return -EINVAL;
218
219         /* - Open the shared memory for the attach_chan_name
220          * - Point to the shared session for this Device instance
221          * - Check that session is valid
222          * - Attach to the firmware so it can record there is more
223          *   than one client of the session.
224          */
225
226         if (tfp->session) {
227                 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
228                         rc = tf_msg_session_attach(tfp,
229                                                    parms->ctrl_chan_name,
230                                                    parms->session_id);
231                 }
232         }
233 #endif /* TF_SHARED */
234         return -1;
235 }
236
237 int
238 tf_close_session(struct tf *tfp)
239 {
240         int rc;
241         int rc_close = 0;
242         struct tf_session *tfs;
243         union tf_session_id session_id;
244
245         if (tfp == NULL || tfp->session == NULL)
246                 return -EINVAL;
247
248         tfs = (struct tf_session *)(tfp->session->core_data);
249
250         /* Cleanup if we're last user of the session */
251         if (tfs->ref_count == 1) {
252                 /* Cleanup any outstanding resources */
253                 rc_close = tf_rm_close(tfp);
254         }
255
256         if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
257                 rc = tf_msg_session_close(tfp);
258                 if (rc) {
259                         /* Log error */
260                         PMD_DRV_LOG(ERR,
261                                     "Message send failed, rc:%d\n",
262                                     rc);
263                 }
264
265                 /* Update the ref_count */
266                 tfs->ref_count--;
267         }
268
269         session_id = tfs->session_id;
270
271         /* Final cleanup as we're last user of the session */
272         if (tfs->ref_count == 0) {
273                 tfp_free(tfp->session->core_data);
274                 tfp_free(tfp->session);
275                 tfp->session = NULL;
276         }
277
278         PMD_DRV_LOG(INFO,
279                     "Session closed, session_id:%d\n",
280                     session_id.id);
281
282         PMD_DRV_LOG(INFO,
283                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
284                     session_id.internal.domain,
285                     session_id.internal.bus,
286                     session_id.internal.device,
287                     session_id.internal.fw_session_id);
288
289         return rc_close;
290 }
291
292 /** allocate identifier resource
293  *
294  * Returns success or failure code.
295  */
296 int tf_alloc_identifier(struct tf *tfp,
297                         struct tf_alloc_identifier_parms *parms)
298 {
299         struct bitalloc *session_pool;
300         struct tf_session *tfs;
301         int id;
302         int rc;
303
304         if (parms == NULL || tfp == NULL)
305                 return -EINVAL;
306
307         if (tfp->session == NULL || tfp->session->core_data == NULL) {
308                 PMD_DRV_LOG(ERR, "%s: session error\n",
309                             tf_dir_2_str(parms->dir));
310                 return -EINVAL;
311         }
312
313         tfs = (struct tf_session *)(tfp->session->core_data);
314
315         switch (parms->ident_type) {
316         case TF_IDENT_TYPE_L2_CTXT:
317                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
318                                 TF_L2_CTXT_REMAP_POOL_NAME,
319                                 rc);
320                 break;
321         case TF_IDENT_TYPE_PROF_FUNC:
322                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
323                                 TF_PROF_FUNC_POOL_NAME,
324                                 rc);
325                 break;
326         case TF_IDENT_TYPE_EM_PROF:
327                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
328                                 TF_EM_PROF_ID_POOL_NAME,
329                                 rc);
330                 break;
331         case TF_IDENT_TYPE_WC_PROF:
332                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
333                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
334                                 rc);
335                 break;
336         case TF_IDENT_TYPE_L2_FUNC:
337                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
338                             tf_dir_2_str(parms->dir),
339                             tf_ident_2_str(parms->ident_type));
340                 rc = -EOPNOTSUPP;
341                 break;
342         default:
343                 PMD_DRV_LOG(ERR, "%s: %s\n",
344                             tf_dir_2_str(parms->dir),
345                             tf_ident_2_str(parms->ident_type));
346                 rc = -EINVAL;
347                 break;
348         }
349
350         if (rc) {
351                 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
352                             tf_dir_2_str(parms->dir),
353                             tf_ident_2_str(parms->ident_type));
354                 return rc;
355         }
356
357         id = ba_alloc(session_pool);
358
359         if (id == BA_FAIL) {
360                 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
361                             tf_dir_2_str(parms->dir),
362                             tf_ident_2_str(parms->ident_type));
363                 return -ENOMEM;
364         }
365         parms->id = id;
366         return 0;
367 }
368
369 /** free identifier resource
370  *
371  * Returns success or failure code.
372  */
373 int tf_free_identifier(struct tf *tfp,
374                        struct tf_free_identifier_parms *parms)
375 {
376         struct bitalloc *session_pool;
377         int rc;
378         int ba_rc;
379         struct tf_session *tfs;
380
381         if (parms == NULL || tfp == NULL)
382                 return -EINVAL;
383
384         if (tfp->session == NULL || tfp->session->core_data == NULL) {
385                 PMD_DRV_LOG(ERR, "%s: Session error\n",
386                             tf_dir_2_str(parms->dir));
387                 return -EINVAL;
388         }
389
390         tfs = (struct tf_session *)(tfp->session->core_data);
391
392         switch (parms->ident_type) {
393         case TF_IDENT_TYPE_L2_CTXT:
394                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
395                                 TF_L2_CTXT_REMAP_POOL_NAME,
396                                 rc);
397                 break;
398         case TF_IDENT_TYPE_PROF_FUNC:
399                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
400                                 TF_PROF_FUNC_POOL_NAME,
401                                 rc);
402                 break;
403         case TF_IDENT_TYPE_EM_PROF:
404                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
405                                 TF_EM_PROF_ID_POOL_NAME,
406                                 rc);
407                 break;
408         case TF_IDENT_TYPE_WC_PROF:
409                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
410                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
411                                 rc);
412                 break;
413         case TF_IDENT_TYPE_L2_FUNC:
414                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
415                             tf_dir_2_str(parms->dir),
416                             tf_ident_2_str(parms->ident_type));
417                 rc = -EOPNOTSUPP;
418                 break;
419         default:
420                 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
421                             tf_dir_2_str(parms->dir),
422                             tf_ident_2_str(parms->ident_type));
423                 rc = -EINVAL;
424                 break;
425         }
426         if (rc) {
427                 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
428                             tf_dir_2_str(parms->dir),
429                             tf_ident_2_str(parms->ident_type));
430                 return rc;
431         }
432
433         ba_rc = ba_inuse(session_pool, (int)parms->id);
434
435         if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
436                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
437                             tf_dir_2_str(parms->dir),
438                             tf_ident_2_str(parms->ident_type),
439                             parms->id);
440                 return -EINVAL;
441         }
442
443         ba_free(session_pool, (int)parms->id);
444
445         return 0;
446 }
447
448 int
449 tf_alloc_tcam_entry(struct tf *tfp,
450                     struct tf_alloc_tcam_entry_parms *parms)
451 {
452         int rc;
453         int index;
454         struct tf_session *tfs;
455         struct bitalloc *session_pool;
456
457         if (parms == NULL || tfp == NULL)
458                 return -EINVAL;
459
460         if (tfp->session == NULL || tfp->session->core_data == NULL) {
461                 PMD_DRV_LOG(ERR, "%s: session error\n",
462                             tf_dir_2_str(parms->dir));
463                 return -EINVAL;
464         }
465
466         tfs = (struct tf_session *)(tfp->session->core_data);
467
468         rc = tf_rm_lookup_tcam_type_pool(tfs,
469                                          parms->dir,
470                                          parms->tcam_tbl_type,
471                                          &session_pool);
472         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
473         if (rc)
474                 return rc;
475
476         index = ba_alloc(session_pool);
477         if (index == BA_FAIL) {
478                 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
479                             tf_dir_2_str(parms->dir),
480                             tf_tcam_tbl_2_str(parms->tcam_tbl_type));
481                 return -ENOMEM;
482         }
483
484         parms->idx = index;
485         return 0;
486 }
487
488 int
489 tf_set_tcam_entry(struct tf *tfp,
490                   struct tf_set_tcam_entry_parms *parms)
491 {
492         int rc;
493         int id;
494         struct tf_session *tfs;
495         struct bitalloc *session_pool;
496
497         if (tfp == NULL || parms == NULL) {
498                 PMD_DRV_LOG(ERR, "Invalid parameters\n");
499                 return -EINVAL;
500         }
501
502         if (tfp->session == NULL || tfp->session->core_data == NULL) {
503                 PMD_DRV_LOG(ERR,
504                             "%s, Session info invalid\n",
505                             tf_dir_2_str(parms->dir));
506                 return -EINVAL;
507         }
508
509         tfs = (struct tf_session *)(tfp->session->core_data);
510
511         /*
512          * Each tcam send msg function should check for key sizes range
513          */
514
515         rc = tf_rm_lookup_tcam_type_pool(tfs,
516                                          parms->dir,
517                                          parms->tcam_tbl_type,
518                                          &session_pool);
519         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
520         if (rc)
521                 return rc;
522
523
524         /* Verify that the entry has been previously allocated */
525         id = ba_inuse(session_pool, parms->idx);
526         if (id != 1) {
527                 PMD_DRV_LOG(ERR,
528                    "%s: %s: Invalid or not allocated index, idx:%d\n",
529                    tf_dir_2_str(parms->dir),
530                    tf_tcam_tbl_2_str(parms->tcam_tbl_type),
531                    parms->idx);
532                 return -EINVAL;
533         }
534
535         rc = tf_msg_tcam_entry_set(tfp, parms);
536
537         return rc;
538 }
539
540 int
541 tf_get_tcam_entry(struct tf *tfp __rte_unused,
542                   struct tf_get_tcam_entry_parms *parms __rte_unused)
543 {
544         int rc = -EOPNOTSUPP;
545
546         if (tfp == NULL || parms == NULL) {
547                 PMD_DRV_LOG(ERR, "Invalid parameters\n");
548                 return -EINVAL;
549         }
550
551         if (tfp->session == NULL || tfp->session->core_data == NULL) {
552                 PMD_DRV_LOG(ERR,
553                             "%s, Session info invalid\n",
554                             tf_dir_2_str(parms->dir));
555                 return -EINVAL;
556         }
557
558         return rc;
559 }
560
561 int
562 tf_free_tcam_entry(struct tf *tfp,
563                    struct tf_free_tcam_entry_parms *parms)
564 {
565         int rc;
566         struct tf_session *tfs;
567         struct bitalloc *session_pool;
568
569         if (parms == NULL || tfp == NULL)
570                 return -EINVAL;
571
572         if (tfp->session == NULL || tfp->session->core_data == NULL) {
573                 PMD_DRV_LOG(ERR, "%s: Session error\n",
574                             tf_dir_2_str(parms->dir));
575                 return -EINVAL;
576         }
577
578         tfs = (struct tf_session *)(tfp->session->core_data);
579
580         rc = tf_rm_lookup_tcam_type_pool(tfs,
581                                          parms->dir,
582                                          parms->tcam_tbl_type,
583                                          &session_pool);
584         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
585         if (rc)
586                 return rc;
587
588         rc = ba_inuse(session_pool, (int)parms->idx);
589         if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
590                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
591                             tf_dir_2_str(parms->dir),
592                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
593                             parms->idx);
594                 return -EINVAL;
595         }
596
597         ba_free(session_pool, (int)parms->idx);
598
599         rc = tf_msg_tcam_entry_free(tfp, parms);
600         if (rc) {
601                 /* Log error */
602                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
603                             tf_dir_2_str(parms->dir),
604                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
605                             parms->idx);
606         }
607
608         return rc;
609 }