net/bnxt: add TruFlow core identifier
[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_rm.h"
11 #include "tf_msg.h"
12 #include "tfp.h"
13 #include "bitalloc.h"
14 #include "bnxt.h"
15 #include "rand.h"
16
17 static inline uint32_t SWAP_WORDS32(uint32_t val32)
18 {
19         return (((val32 & 0x0000ffff) << 16) |
20                 ((val32 & 0xffff0000) >> 16));
21 }
22
23 static void tf_seeds_init(struct tf_session *session)
24 {
25         int i;
26         uint32_t r;
27
28         /* Initialize the lfsr */
29         rand_init();
30
31         /* RX and TX use the same seed values */
32         session->lkup_lkup3_init_cfg[TF_DIR_RX] =
33                 session->lkup_lkup3_init_cfg[TF_DIR_TX] =
34                                                 SWAP_WORDS32(rand32());
35
36         for (i = 0; i < TF_LKUP_SEED_MEM_SIZE / 2; i++) {
37                 r = SWAP_WORDS32(rand32());
38                 session->lkup_em_seed_mem[TF_DIR_RX][i * 2] = r;
39                 session->lkup_em_seed_mem[TF_DIR_TX][i * 2] = r;
40                 r = SWAP_WORDS32(rand32());
41                 session->lkup_em_seed_mem[TF_DIR_RX][i * 2 + 1] = (r & 0x1);
42                 session->lkup_em_seed_mem[TF_DIR_TX][i * 2 + 1] = (r & 0x1);
43         }
44 }
45
46 int
47 tf_open_session(struct tf                    *tfp,
48                 struct tf_open_session_parms *parms)
49 {
50         int rc;
51         struct tf_session *session;
52         struct tfp_calloc_parms alloc_parms;
53         unsigned int domain, bus, slot, device;
54         uint8_t fw_session_id;
55
56         if (tfp == NULL || parms == NULL)
57                 return -EINVAL;
58
59         /* Filter out any non-supported device types on the Core
60          * side. It is assumed that the Firmware will be supported if
61          * firmware open session succeeds.
62          */
63         if (parms->device_type != TF_DEVICE_TYPE_WH)
64                 return -ENOTSUP;
65
66         /* Build the beginning of session_id */
67         rc = sscanf(parms->ctrl_chan_name,
68                     "%x:%x:%x.%d",
69                     &domain,
70                     &bus,
71                     &slot,
72                     &device);
73         if (rc != 4) {
74                 PMD_DRV_LOG(ERR,
75                             "Failed to scan device ctrl_chan_name\n");
76                 return -EINVAL;
77         }
78
79         /* open FW session and get a new session_id */
80         rc = tf_msg_session_open(tfp,
81                                  parms->ctrl_chan_name,
82                                  &fw_session_id);
83         if (rc) {
84                 /* Log error */
85                 if (rc == -EEXIST)
86                         PMD_DRV_LOG(ERR,
87                                     "Session is already open, rc:%d\n",
88                                     rc);
89                 else
90                         PMD_DRV_LOG(ERR,
91                                     "Open message send failed, rc:%d\n",
92                                     rc);
93
94                 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
95                 return rc;
96         }
97
98         /* Allocate session */
99         alloc_parms.nitems = 1;
100         alloc_parms.size = sizeof(struct tf_session_info);
101         alloc_parms.alignment = 0;
102         rc = tfp_calloc(&alloc_parms);
103         if (rc) {
104                 /* Log error */
105                 PMD_DRV_LOG(ERR,
106                             "Failed to allocate session info, rc:%d\n",
107                             rc);
108                 goto cleanup;
109         }
110
111         tfp->session = (struct tf_session_info *)alloc_parms.mem_va;
112
113         /* Allocate core data for the session */
114         alloc_parms.nitems = 1;
115         alloc_parms.size = sizeof(struct tf_session);
116         alloc_parms.alignment = 0;
117         rc = tfp_calloc(&alloc_parms);
118         if (rc) {
119                 /* Log error */
120                 PMD_DRV_LOG(ERR,
121                             "Failed to allocate session data, rc:%d\n",
122                             rc);
123                 goto cleanup;
124         }
125
126         tfp->session->core_data = alloc_parms.mem_va;
127
128         session = (struct tf_session *)tfp->session->core_data;
129         tfp_memcpy(session->ctrl_chan_name,
130                    parms->ctrl_chan_name,
131                    TF_SESSION_NAME_MAX);
132
133         /* Initialize Session */
134         session->device_type = parms->device_type;
135         tf_rm_init(tfp);
136
137         /* Construct the Session ID */
138         session->session_id.internal.domain = domain;
139         session->session_id.internal.bus = bus;
140         session->session_id.internal.device = device;
141         session->session_id.internal.fw_session_id = fw_session_id;
142
143         rc = tf_msg_session_qcfg(tfp);
144         if (rc) {
145                 /* Log error */
146                 PMD_DRV_LOG(ERR,
147                             "Query config message send failed, rc:%d\n",
148                             rc);
149                 goto cleanup_close;
150         }
151
152         /* Shadow DB configuration */
153         if (parms->shadow_copy) {
154                 /* Ignore shadow_copy setting */
155                 session->shadow_copy = 0;/* parms->shadow_copy; */
156 #if (TF_SHADOW == 1)
157                 rc = tf_rm_shadow_db_init(tfs);
158                 if (rc)
159                         PMD_DRV_LOG(ERR,
160                                     "Shadow DB Initialization failed\n, rc:%d",
161                                     rc);
162                 /* Add additional processing */
163 #endif /* TF_SHADOW */
164         }
165
166         /* Adjust the Session with what firmware allowed us to get */
167         rc = tf_rm_allocate_validate(tfp);
168         if (rc) {
169                 /* Log error */
170                 goto cleanup_close;
171         }
172
173         /* Setup hash seeds */
174         tf_seeds_init(session);
175
176         session->ref_count++;
177
178         /* Return session ID */
179         parms->session_id = session->session_id;
180
181         PMD_DRV_LOG(INFO,
182                     "Session created, session_id:%d\n",
183                     parms->session_id.id);
184
185         PMD_DRV_LOG(INFO,
186                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
187                     parms->session_id.internal.domain,
188                     parms->session_id.internal.bus,
189                     parms->session_id.internal.device,
190                     parms->session_id.internal.fw_session_id);
191
192         return 0;
193
194  cleanup:
195         tfp_free(tfp->session->core_data);
196         tfp_free(tfp->session);
197         tfp->session = NULL;
198         return rc;
199
200  cleanup_close:
201         tf_close_session(tfp);
202         return -EINVAL;
203 }
204
205 int
206 tf_attach_session(struct tf *tfp __rte_unused,
207                   struct tf_attach_session_parms *parms __rte_unused)
208 {
209 #if (TF_SHARED == 1)
210         int rc;
211
212         if (tfp == NULL)
213                 return -EINVAL;
214
215         /* - Open the shared memory for the attach_chan_name
216          * - Point to the shared session for this Device instance
217          * - Check that session is valid
218          * - Attach to the firmware so it can record there is more
219          *   than one client of the session.
220          */
221
222         if (tfp->session) {
223                 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
224                         rc = tf_msg_session_attach(tfp,
225                                                    parms->ctrl_chan_name,
226                                                    parms->session_id);
227                 }
228         }
229 #endif /* TF_SHARED */
230         return -1;
231 }
232
233 int
234 tf_close_session(struct tf *tfp)
235 {
236         int rc;
237         int rc_close = 0;
238         struct tf_session *tfs;
239         union tf_session_id session_id;
240
241         if (tfp == NULL || tfp->session == NULL)
242                 return -EINVAL;
243
244         tfs = (struct tf_session *)(tfp->session->core_data);
245
246         /* Cleanup if we're last user of the session */
247         if (tfs->ref_count == 1) {
248                 /* Cleanup any outstanding resources */
249                 rc_close = tf_rm_close(tfp);
250         }
251
252         if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
253                 rc = tf_msg_session_close(tfp);
254                 if (rc) {
255                         /* Log error */
256                         PMD_DRV_LOG(ERR,
257                                     "Message send failed, rc:%d\n",
258                                     rc);
259                 }
260
261                 /* Update the ref_count */
262                 tfs->ref_count--;
263         }
264
265         session_id = tfs->session_id;
266
267         /* Final cleanup as we're last user of the session */
268         if (tfs->ref_count == 0) {
269                 tfp_free(tfp->session->core_data);
270                 tfp_free(tfp->session);
271                 tfp->session = NULL;
272         }
273
274         PMD_DRV_LOG(INFO,
275                     "Session closed, session_id:%d\n",
276                     session_id.id);
277
278         PMD_DRV_LOG(INFO,
279                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
280                     session_id.internal.domain,
281                     session_id.internal.bus,
282                     session_id.internal.device,
283                     session_id.internal.fw_session_id);
284
285         return rc_close;
286 }
287
288 /** allocate identifier resource
289  *
290  * Returns success or failure code.
291  */
292 int tf_alloc_identifier(struct tf *tfp,
293                         struct tf_alloc_identifier_parms *parms)
294 {
295         struct bitalloc *session_pool;
296         struct tf_session *tfs;
297         int id;
298         int rc;
299
300         if (parms == NULL || tfp == NULL)
301                 return -EINVAL;
302
303         if (tfp->session == NULL || tfp->session->core_data == NULL) {
304                 PMD_DRV_LOG(ERR, "%s: session error\n",
305                             tf_dir_2_str(parms->dir));
306                 return -EINVAL;
307         }
308
309         tfs = (struct tf_session *)(tfp->session->core_data);
310
311         switch (parms->ident_type) {
312         case TF_IDENT_TYPE_L2_CTXT:
313                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
314                                 TF_L2_CTXT_REMAP_POOL_NAME,
315                                 rc);
316                 break;
317         case TF_IDENT_TYPE_PROF_FUNC:
318                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
319                                 TF_PROF_FUNC_POOL_NAME,
320                                 rc);
321                 break;
322         case TF_IDENT_TYPE_EM_PROF:
323                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
324                                 TF_EM_PROF_ID_POOL_NAME,
325                                 rc);
326                 break;
327         case TF_IDENT_TYPE_WC_PROF:
328                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
329                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
330                                 rc);
331                 break;
332         case TF_IDENT_TYPE_L2_FUNC:
333                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
334                             tf_dir_2_str(parms->dir),
335                             tf_ident_2_str(parms->ident_type));
336                 rc = -EOPNOTSUPP;
337                 break;
338         default:
339                 PMD_DRV_LOG(ERR, "%s: %s\n",
340                             tf_dir_2_str(parms->dir),
341                             tf_ident_2_str(parms->ident_type));
342                 rc = -EINVAL;
343                 break;
344         }
345
346         if (rc) {
347                 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
348                             tf_dir_2_str(parms->dir),
349                             tf_ident_2_str(parms->ident_type));
350                 return rc;
351         }
352
353         id = ba_alloc(session_pool);
354
355         if (id == BA_FAIL) {
356                 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
357                             tf_dir_2_str(parms->dir),
358                             tf_ident_2_str(parms->ident_type));
359                 return -ENOMEM;
360         }
361         parms->id = id;
362         return 0;
363 }
364
365 /** free identifier resource
366  *
367  * Returns success or failure code.
368  */
369 int tf_free_identifier(struct tf *tfp,
370                        struct tf_free_identifier_parms *parms)
371 {
372         struct bitalloc *session_pool;
373         int rc;
374         int ba_rc;
375         struct tf_session *tfs;
376
377         if (parms == NULL || tfp == NULL)
378                 return -EINVAL;
379
380         if (tfp->session == NULL || tfp->session->core_data == NULL) {
381                 PMD_DRV_LOG(ERR, "%s: Session error\n",
382                             tf_dir_2_str(parms->dir));
383                 return -EINVAL;
384         }
385
386         tfs = (struct tf_session *)(tfp->session->core_data);
387
388         switch (parms->ident_type) {
389         case TF_IDENT_TYPE_L2_CTXT:
390                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
391                                 TF_L2_CTXT_REMAP_POOL_NAME,
392                                 rc);
393                 break;
394         case TF_IDENT_TYPE_PROF_FUNC:
395                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
396                                 TF_PROF_FUNC_POOL_NAME,
397                                 rc);
398                 break;
399         case TF_IDENT_TYPE_EM_PROF:
400                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
401                                 TF_EM_PROF_ID_POOL_NAME,
402                                 rc);
403                 break;
404         case TF_IDENT_TYPE_WC_PROF:
405                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
406                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
407                                 rc);
408                 break;
409         case TF_IDENT_TYPE_L2_FUNC:
410                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
411                             tf_dir_2_str(parms->dir),
412                             tf_ident_2_str(parms->ident_type));
413                 rc = -EOPNOTSUPP;
414                 break;
415         default:
416                 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
417                             tf_dir_2_str(parms->dir),
418                             tf_ident_2_str(parms->ident_type));
419                 rc = -EINVAL;
420                 break;
421         }
422         if (rc) {
423                 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
424                             tf_dir_2_str(parms->dir),
425                             tf_ident_2_str(parms->ident_type));
426                 return rc;
427         }
428
429         ba_rc = ba_inuse(session_pool, (int)parms->id);
430
431         if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
432                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
433                             tf_dir_2_str(parms->dir),
434                             tf_ident_2_str(parms->ident_type),
435                             parms->id);
436                 return -EINVAL;
437         }
438
439         ba_free(session_pool, (int)parms->id);
440
441         return 0;
442 }