Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <string.h>
7 : : #include <rte_common.h>
8 : : #include "tf_session.h"
9 : : #include "tf_common.h"
10 : : #include "tf_msg.h"
11 : : #include "tfp.h"
12 : : #include "bnxt.h"
13 : :
14 : : struct tf_session_client_create_parms {
15 : : /**
16 : : * [in] Pointer to the control channel name string
17 : : */
18 : : char *ctrl_chan_name;
19 : :
20 : : /**
21 : : * [out] Firmware Session Client ID
22 : : */
23 : : union tf_session_client_id *session_client_id;
24 : : };
25 : :
26 : : struct tf_session_client_destroy_parms {
27 : : /**
28 : : * FW Session Client Identifier
29 : : */
30 : : union tf_session_client_id session_client_id;
31 : : };
32 : :
33 : : /**
34 : : * Creates a Session and the associated client.
35 : : *
36 : : * [in] tfp
37 : : * Pointer to TF handle
38 : : *
39 : : * [in] parms
40 : : * Pointer to session client create parameters
41 : : *
42 : : * Returns
43 : : * - (0) if successful.
44 : : * - (-EINVAL) on failure.
45 : : * - (-ENOMEM) if max session clients has been reached.
46 : : */
47 : : static int
48 : 0 : tf_session_create(struct tf *tfp,
49 : : struct tf_session_open_session_parms *parms)
50 : : {
51 : : int rc;
52 : : struct tf_session *session = NULL;
53 : : struct tf_session_client *client;
54 : : struct tfp_calloc_parms cparms;
55 : : uint8_t fw_session_id;
56 : : uint8_t fw_session_client_id;
57 : : union tf_session_id *session_id;
58 : : struct tf_dev_info dev;
59 : : bool shared_session_creator;
60 : : char *shared_name;
61 : : char *tcam_session_name;
62 : : char *pool_session_name;
63 : :
64 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
65 : :
66 : 0 : tf_dev_bind_ops(parms->open_cfg->device_type,
67 : : &dev);
68 : :
69 : : /* Open FW session and get a new session_id */
70 : 0 : rc = tf_msg_session_open(parms->open_cfg->bp,
71 : 0 : parms->open_cfg->ctrl_chan_name,
72 : : &fw_session_id,
73 : : &fw_session_client_id,
74 : : &dev,
75 : : &shared_session_creator);
76 [ # # ]: 0 : if (rc) {
77 : : /* Log error */
78 [ # # ]: 0 : if (rc == -EEXIST)
79 : 0 : TFP_DRV_LOG(ERR,
80 : : "Session is already open, rc:%s\n",
81 : : strerror(-rc));
82 : : else
83 : 0 : TFP_DRV_LOG(ERR,
84 : : "Open message send failed, rc:%s\n",
85 : : strerror(-rc));
86 : :
87 : 0 : parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
88 : 0 : return rc;
89 : : }
90 : :
91 : : /* Allocate session */
92 : 0 : cparms.nitems = 1;
93 : 0 : cparms.size = sizeof(struct tf_session_info);
94 : 0 : cparms.alignment = 0;
95 : 0 : rc = tfp_calloc(&cparms);
96 [ # # ]: 0 : if (rc) {
97 : : /* Log error */
98 : 0 : TFP_DRV_LOG(ERR,
99 : : "Failed to allocate session info, rc:%s\n",
100 : : strerror(-rc));
101 : 0 : goto cleanup;
102 : : }
103 : 0 : tfp->session = (struct tf_session_info *)cparms.mem_va;
104 : :
105 : : /* Allocate core data for the session */
106 : 0 : cparms.nitems = 1;
107 : 0 : cparms.size = sizeof(struct tf_session);
108 : 0 : cparms.alignment = 0;
109 : 0 : rc = tfp_calloc(&cparms);
110 [ # # ]: 0 : if (rc) {
111 : : /* Log error */
112 : 0 : TFP_DRV_LOG(ERR,
113 : : "Failed to allocate session data, rc:%s\n",
114 : : strerror(-rc));
115 : 0 : goto cleanup;
116 : : }
117 : 0 : tfp->session->core_data = cparms.mem_va;
118 : 0 : session_id = &parms->open_cfg->session_id;
119 : :
120 : : /* Update Session Info, which is what is visible to the caller */
121 : 0 : tfp->session->ver.major = 0;
122 : 0 : tfp->session->ver.minor = 0;
123 : 0 : tfp->session->ver.update = 0;
124 : :
125 : 0 : tfp->session->session_id.internal.domain = session_id->internal.domain;
126 : 0 : tfp->session->session_id.internal.bus = session_id->internal.bus;
127 : 0 : tfp->session->session_id.internal.device = session_id->internal.device;
128 : 0 : tfp->session->session_id.internal.fw_session_id = fw_session_id;
129 : :
130 : : /* Initialize Session and Device, which is private */
131 : : session = (struct tf_session *)tfp->session->core_data;
132 : 0 : session->ver.major = 0;
133 : 0 : session->ver.minor = 0;
134 : 0 : session->ver.update = 0;
135 : :
136 : 0 : session->session_id.internal.domain = session_id->internal.domain;
137 : 0 : session->session_id.internal.bus = session_id->internal.bus;
138 : 0 : session->session_id.internal.device = session_id->internal.device;
139 : 0 : session->session_id.internal.fw_session_id = fw_session_id;
140 : : /* Return the allocated session id */
141 : 0 : session_id->id = session->session_id.id;
142 : :
143 : : /* Init session client list */
144 : 0 : ll_init(&session->client_ll);
145 : :
146 : : /* Create the local session client, initialize and attach to
147 : : * the session
148 : : */
149 : 0 : cparms.nitems = 1;
150 : 0 : cparms.size = sizeof(struct tf_session_client);
151 : 0 : cparms.alignment = 0;
152 : 0 : rc = tfp_calloc(&cparms);
153 [ # # ]: 0 : if (rc) {
154 : : /* Log error */
155 : 0 : TFP_DRV_LOG(ERR,
156 : : "Failed to allocate session client, rc:%s\n",
157 : : strerror(-rc));
158 : 0 : goto cleanup;
159 : : }
160 : 0 : client = cparms.mem_va;
161 : :
162 : : /* Register FID with the client */
163 : 0 : rc = tfp_get_fid(tfp, &client->fw_fid);
164 [ # # ]: 0 : if (rc)
165 : : return rc;
166 : :
167 : 0 : client->session_client_id.internal.fw_session_id = fw_session_id;
168 : 0 : client->session_client_id.internal.fw_session_client_id =
169 : : fw_session_client_id;
170 : :
171 : 0 : tfp_memcpy(client->ctrl_chan_name,
172 : 0 : parms->open_cfg->ctrl_chan_name,
173 : : TF_SESSION_NAME_MAX);
174 : :
175 : 0 : ll_insert(&session->client_ll, &client->ll_entry);
176 : 0 : session->ref_count++;
177 : :
178 : : /* Init session em_ext_db */
179 : 0 : session->em_ext_db_handle = NULL;
180 : :
181 : : /* Populate the request */
182 : 0 : shared_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared");
183 [ # # ]: 0 : if (shared_name) {
184 : 0 : session->shared_session = true;
185 : : /*
186 : : * "tf_shared-wc_tcam" is defined for tf_fw version 1.0.0.
187 : : * "tf_shared-pool" is defined for version 1.0.1.
188 : : */
189 : 0 : tcam_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-wc_tcam");
190 : 0 : pool_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-pool");
191 [ # # ]: 0 : if (tcam_session_name || pool_session_name)
192 : 0 : session->shared_session_hotup = true;
193 : : }
194 : :
195 [ # # # # ]: 0 : if (session->shared_session && shared_session_creator) {
196 : 0 : session->shared_session_creator = true;
197 : 0 : parms->open_cfg->shared_session_creator = true;
198 : : }
199 : :
200 : 0 : rc = tf_dev_bind(tfp,
201 : : parms->open_cfg->device_type,
202 : : &parms->open_cfg->resources,
203 : 0 : parms->open_cfg->wc_num_slices,
204 : : &session->dev);
205 : :
206 : : /* Logging handled by dev_bind */
207 [ # # ]: 0 : if (rc)
208 : 0 : goto cleanup;
209 : :
210 [ # # ]: 0 : if (session->dev.ops->tf_dev_get_mailbox == NULL) {
211 : : /* Log error */
212 : 0 : TFP_DRV_LOG(ERR,
213 : : "No tf_dev_get_mailbox() defined for device\n");
214 : 0 : goto cleanup;
215 : : }
216 : :
217 : 0 : session->dev_init = true;
218 : :
219 : 0 : return 0;
220 : :
221 : 0 : cleanup:
222 : 0 : rc = tf_msg_session_close(tfp,
223 : : fw_session_id,
224 : 0 : dev.ops->tf_dev_get_mailbox());
225 [ # # ]: 0 : if (rc) {
226 : : /* Log error */
227 : 0 : TFP_DRV_LOG(ERR,
228 : : "FW Session close failed, rc:%s\n",
229 : : strerror(-rc));
230 : : }
231 [ # # ]: 0 : if (tfp->session) {
232 : 0 : tfp_free(tfp->session->core_data);
233 : 0 : tfp_free(tfp->session);
234 : 0 : tfp->session = NULL;
235 : : }
236 : :
237 : : return rc;
238 : : }
239 : :
240 : : /**
241 : : * Creates a Session Client on an existing Session.
242 : : *
243 : : * [in] tfp
244 : : * Pointer to TF handle
245 : : *
246 : : * [in] parms
247 : : * Pointer to session client create parameters
248 : : *
249 : : * Returns
250 : : * - (0) if successful.
251 : : * - (-EINVAL) on failure.
252 : : * - (-ENOMEM) if max session clients has been reached.
253 : : */
254 : : static int
255 : 0 : tf_session_client_create(struct tf *tfp,
256 : : struct tf_session_client_create_parms *parms)
257 : : {
258 : : int rc;
259 : 0 : struct tf_session *session = NULL;
260 : : struct tf_session_client *client;
261 : : struct tfp_calloc_parms cparms;
262 : : union tf_session_client_id session_client_id;
263 : :
264 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
265 : :
266 : : /* Using internal version as session client may not exist yet */
267 : 0 : rc = tf_session_get_session_internal(tfp, &session);
268 [ # # ]: 0 : if (rc) {
269 : 0 : TFP_DRV_LOG(ERR,
270 : : "Failed to lookup session, rc:%s\n",
271 : : strerror(-rc));
272 : 0 : return rc;
273 : : }
274 : :
275 : 0 : client = tf_session_find_session_client_by_name(session,
276 : 0 : parms->ctrl_chan_name);
277 [ # # ]: 0 : if (client) {
278 : 0 : TFP_DRV_LOG(ERR,
279 : : "Client %s, already registered with this session\n",
280 : : parms->ctrl_chan_name);
281 : 0 : return -EOPNOTSUPP;
282 : : }
283 : :
284 : 0 : rc = tf_msg_session_client_register
285 : : (tfp,
286 : : session,
287 : : parms->ctrl_chan_name,
288 : : &session_client_id.internal.fw_session_client_id);
289 [ # # ]: 0 : if (rc) {
290 : 0 : TFP_DRV_LOG(ERR,
291 : : "Failed to create client on session, rc:%s\n",
292 : : strerror(-rc));
293 : 0 : return rc;
294 : : }
295 : :
296 : : /* Create the local session client, initialize and attach to
297 : : * the session
298 : : */
299 : 0 : cparms.nitems = 1;
300 : 0 : cparms.size = sizeof(struct tf_session_client);
301 : 0 : cparms.alignment = 0;
302 : 0 : rc = tfp_calloc(&cparms);
303 [ # # ]: 0 : if (rc) {
304 : 0 : TFP_DRV_LOG(ERR,
305 : : "Failed to allocate session client, rc:%s\n",
306 : : strerror(-rc));
307 : 0 : goto cleanup;
308 : : }
309 : 0 : client = cparms.mem_va;
310 : :
311 : : /* Register FID with the client */
312 : 0 : rc = tfp_get_fid(tfp, &client->fw_fid);
313 [ # # ]: 0 : if (rc)
314 : : return rc;
315 : :
316 : : /* Build the Session Client ID by adding the fw_session_id */
317 : 0 : rc = tf_session_get_fw_session_id
318 : : (tfp,
319 : : &session_client_id.internal.fw_session_id);
320 [ # # ]: 0 : if (rc) {
321 : 0 : TFP_DRV_LOG(ERR,
322 : : "Session Firmware id lookup failed, rc:%s\n",
323 : : strerror(-rc));
324 : 0 : return rc;
325 : : }
326 : :
327 : 0 : tfp_memcpy(client->ctrl_chan_name,
328 : 0 : parms->ctrl_chan_name,
329 : : TF_SESSION_NAME_MAX);
330 : :
331 : 0 : client->session_client_id.id = session_client_id.id;
332 : :
333 : 0 : ll_insert(&session->client_ll, &client->ll_entry);
334 : :
335 : 0 : session->ref_count++;
336 : :
337 : : /* Build the return value */
338 : 0 : parms->session_client_id->id = session_client_id.id;
339 : :
340 : : cleanup:
341 : : /* TBD - Add code to unregister newly create client from fw */
342 : :
343 : : return rc;
344 : : }
345 : :
346 : : /**
347 : : * Destroys a Session Client on an existing Session.
348 : : *
349 : : * [in] tfp
350 : : * Pointer to TF handle
351 : : *
352 : : * [in] parms
353 : : * Pointer to the session client destroy parameters
354 : : *
355 : : * Returns
356 : : * - (0) if successful.
357 : : * - (-EINVAL) on failure.
358 : : * - (-ENOTFOUND) error, client not owned by the session.
359 : : * - (-ENOTSUPP) error, unable to destroy client as its the last
360 : : * client. Please use the tf_session_close().
361 : : */
362 : : static int
363 : 0 : tf_session_client_destroy(struct tf *tfp,
364 : : struct tf_session_client_destroy_parms *parms)
365 : : {
366 : : int rc;
367 : : struct tf_session *tfs;
368 : : struct tf_session_client *client;
369 : :
370 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
371 : :
372 : 0 : rc = tf_session_get_session(tfp, &tfs);
373 [ # # ]: 0 : if (rc) {
374 : 0 : TFP_DRV_LOG(ERR,
375 : : "Failed to lookup session, rc:%s\n",
376 : : strerror(-rc));
377 : 0 : return rc;
378 : : }
379 : :
380 : : /* Check session owns this client and that we're not the last client */
381 : 0 : client = tf_session_get_session_client(tfs,
382 : : parms->session_client_id);
383 [ # # ]: 0 : if (client == NULL) {
384 : 0 : TFP_DRV_LOG(ERR,
385 : : "Client %d, not found within this session\n",
386 : : parms->session_client_id.id);
387 : 0 : return -EINVAL;
388 : : }
389 : :
390 : : /* If last client the request is rejected and cleanup should
391 : : * be done by session close.
392 : : */
393 [ # # ]: 0 : if (tfs->ref_count == 1)
394 : : return -EOPNOTSUPP;
395 : :
396 : 0 : rc = tf_msg_session_client_unregister
397 : : (tfp,
398 : : tfs,
399 : 0 : parms->session_client_id.internal.fw_session_client_id);
400 : :
401 : : /* Log error, but continue. If FW fails we do not really have
402 : : * a way to fix this but the client would no longer be valid
403 : : * thus we remove from the session.
404 : : */
405 [ # # ]: 0 : if (rc) {
406 : 0 : TFP_DRV_LOG(ERR,
407 : : "Client destroy on FW Failed, rc:%s\n",
408 : : strerror(-rc));
409 : : }
410 : :
411 : 0 : ll_delete(&tfs->client_ll, &client->ll_entry);
412 : :
413 : : /* Decrement the session ref_count */
414 : 0 : tfs->ref_count--;
415 : :
416 : 0 : tfp_free(client);
417 : :
418 : 0 : return rc;
419 : : }
420 : :
421 : : int
422 : 0 : tf_session_open_session(struct tf *tfp,
423 : : struct tf_session_open_session_parms *parms)
424 : : {
425 : : int rc;
426 : : struct tf_session_client_create_parms scparms;
427 : :
428 [ # # # # ]: 0 : TF_CHECK_PARMS3(tfp, parms, parms->open_cfg->bp);
429 : :
430 : 0 : tfp->bp = parms->open_cfg->bp;
431 : : /* Decide if we're creating a new session or session client */
432 [ # # ]: 0 : if (tfp->session == NULL) {
433 : 0 : rc = tf_session_create(tfp, parms);
434 [ # # ]: 0 : if (rc) {
435 : 0 : TFP_DRV_LOG(ERR,
436 : : "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
437 : : parms->open_cfg->ctrl_chan_name,
438 : : strerror(-rc));
439 : 0 : return rc;
440 : : }
441 : :
442 : 0 : TFP_DRV_LOG(INFO,
443 : : "Session created, session_client_id:%d,"
444 : : " session_id:0x%08x, fw_session_id:%d\n",
445 : : parms->open_cfg->session_client_id.id,
446 : : parms->open_cfg->session_id.id,
447 : : parms->open_cfg->session_id.internal.fw_session_id);
448 : : } else {
449 : 0 : scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
450 : 0 : scparms.session_client_id = &parms->open_cfg->session_client_id;
451 : :
452 : : /* Create the new client and get it associated with
453 : : * the session.
454 : : */
455 : 0 : rc = tf_session_client_create(tfp, &scparms);
456 [ # # ]: 0 : if (rc) {
457 : 0 : TFP_DRV_LOG(ERR,
458 : : "Failed to create client on session 0x%x, rc:%s\n",
459 : : parms->open_cfg->session_id.id,
460 : : strerror(-rc));
461 : 0 : return rc;
462 : : }
463 : :
464 : 0 : TFP_DRV_LOG(INFO,
465 : : "Session Client:%d registered on session:0x%08x\n",
466 : : scparms.session_client_id->internal.fw_session_client_id,
467 : : tfp->session->session_id.id);
468 : : }
469 : :
470 : : return 0;
471 : : }
472 : :
473 : : int
474 : 0 : tf_session_attach_session(struct tf *tfp __rte_unused,
475 : : struct tf_session_attach_session_parms *parms __rte_unused)
476 : : {
477 : : int rc = -EOPNOTSUPP;
478 : :
479 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
480 : :
481 : 0 : TFP_DRV_LOG(ERR,
482 : : "Attach not yet supported, rc:%s\n",
483 : : strerror(-rc));
484 : 0 : return rc;
485 : : }
486 : :
487 : : int
488 : 0 : tf_session_close_session(struct tf *tfp,
489 : : struct tf_session_close_session_parms *parms)
490 : : {
491 : : int rc;
492 : 0 : struct tf_session *tfs = NULL;
493 : : struct tf_session_client *client;
494 : 0 : struct tf_dev_info *tfd = NULL;
495 : : struct tf_session_client_destroy_parms scdparms;
496 : : uint16_t fid;
497 : 0 : uint8_t fw_session_id = 1;
498 : : int mailbox = 0;
499 : :
500 [ # # ]: 0 : TF_CHECK_PARMS2(tfp, parms);
501 : :
502 : 0 : rc = tf_session_get_session(tfp, &tfs);
503 [ # # ]: 0 : if (rc) {
504 : 0 : TFP_DRV_LOG(ERR,
505 : : "Session lookup failed, rc:%s\n",
506 : : strerror(-rc));
507 : 0 : return rc;
508 : : }
509 : :
510 [ # # ]: 0 : if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
511 : : rc = -EINVAL;
512 : 0 : TFP_DRV_LOG(ERR,
513 : : "Invalid session id, unable to close, rc:%s\n",
514 : : strerror(-rc));
515 : 0 : return rc;
516 : : }
517 : :
518 : : /* Get the client, we need it independently of the closure
519 : : * type (client or session closure).
520 : : *
521 : : * We find the client by way of the fid. Thus one cannot close
522 : : * a client on behalf of someone else.
523 : : */
524 : 0 : rc = tfp_get_fid(tfp, &fid);
525 [ # # ]: 0 : if (rc)
526 : : return rc;
527 : :
528 : 0 : client = tf_session_find_session_client_by_fid(tfs,
529 : : fid);
530 [ # # ]: 0 : if (!client) {
531 : : rc = -EINVAL;
532 : 0 : TFP_DRV_LOG(ERR,
533 : : "Client not part of the session, unable to close, rc:%s\n",
534 : : strerror(-rc));
535 : 0 : return rc;
536 : : }
537 : :
538 : : /* Record the session we're closing so the caller knows the
539 : : * details.
540 : : */
541 : 0 : *parms->session_id = tfs->session_id;
542 : :
543 : : /* In case multiple clients we chose to close those first */
544 [ # # ]: 0 : if (tfs->ref_count > 1) {
545 : : /* Linaro gcc can't static init this structure */
546 : : memset(&scdparms,
547 : : 0,
548 : : sizeof(struct tf_session_client_destroy_parms));
549 : :
550 : 0 : scdparms.session_client_id = client->session_client_id;
551 : : /* Destroy requested client so its no longer
552 : : * registered with this session.
553 : : */
554 : 0 : rc = tf_session_client_destroy(tfp, &scdparms);
555 [ # # ]: 0 : if (rc) {
556 : 0 : TFP_DRV_LOG(ERR,
557 : : "Failed to unregister Client %d, rc:%s\n",
558 : : client->session_client_id.id,
559 : : strerror(-rc));
560 : 0 : return rc;
561 : : }
562 : :
563 : 0 : TFP_DRV_LOG(INFO,
564 : : "Closed session client, session_client_id:%d\n",
565 : : client->session_client_id.id);
566 : :
567 : 0 : TFP_DRV_LOG(INFO,
568 : : "session_id:0x%08x, ref_count:%d\n",
569 : : tfs->session_id.id,
570 : : tfs->ref_count);
571 : :
572 : 0 : return 0;
573 : : }
574 : :
575 : 0 : rc = tf_session_get_device(tfs, &tfd);
576 [ # # ]: 0 : if (rc) {
577 : 0 : TFP_DRV_LOG(ERR,
578 : : "Device lookup failed, rc:%s\n",
579 : : strerror(-rc));
580 : 0 : return rc;
581 : : }
582 : :
583 : 0 : mailbox = tfd->ops->tf_dev_get_mailbox();
584 : :
585 : 0 : rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
586 [ # # ]: 0 : if (rc) {
587 : 0 : TFP_DRV_LOG(ERR,
588 : : "Unable to lookup FW id, rc:%s\n",
589 : : strerror(-rc));
590 : 0 : return rc;
591 : : }
592 : :
593 : : /* Unbind the device */
594 : 0 : rc = tf_dev_unbind(tfp, tfd);
595 [ # # ]: 0 : if (rc) {
596 : : /* Log error */
597 : 0 : TFP_DRV_LOG(ERR,
598 : : "Device unbind failed, rc:%s\n",
599 : : strerror(-rc));
600 : : }
601 : :
602 : 0 : rc = tf_msg_session_close(tfp, fw_session_id, mailbox);
603 [ # # ]: 0 : if (rc) {
604 : : /* Log error */
605 : 0 : TFP_DRV_LOG(ERR,
606 : : "FW Session close failed, rc:%s\n",
607 : : strerror(-rc));
608 : : }
609 : :
610 : : /* Final cleanup as we're last user of the session thus we
611 : : * also delete the last client.
612 : : */
613 : 0 : ll_delete(&tfs->client_ll, &client->ll_entry);
614 : 0 : tfp_free(client);
615 : :
616 : 0 : tfs->ref_count--;
617 : :
618 : 0 : TFP_DRV_LOG(INFO,
619 : : "Closed session, session_id:0x%08x, ref_count:%d\n",
620 : : tfs->session_id.id,
621 : : tfs->ref_count);
622 : :
623 : 0 : tfs->dev_init = false;
624 : :
625 : 0 : tfp_free(tfp->session->core_data);
626 : 0 : tfp_free(tfp->session);
627 : 0 : tfp->session = NULL;
628 : :
629 : 0 : return 0;
630 : : }
631 : :
632 : : bool
633 : 0 : tf_session_is_fid_supported(struct tf_session *tfs,
634 : : uint16_t fid)
635 : : {
636 : : struct ll_entry *c_entry;
637 : : struct tf_session_client *client;
638 : :
639 : 0 : for (c_entry = tfs->client_ll.head;
640 [ # # ]: 0 : c_entry != NULL;
641 : 0 : c_entry = c_entry->next) {
642 : : client = (struct tf_session_client *)c_entry;
643 [ # # ]: 0 : if (client->fw_fid == fid)
644 : : return true;
645 : : }
646 : :
647 : : return false;
648 : : }
649 : :
650 : : int
651 : 0 : tf_session_get_session_internal(struct tf *tfp,
652 : : struct tf_session **tfs)
653 : : {
654 : : int rc = 0;
655 : :
656 : : /* Skip using the check macro as we want to control the error msg */
657 [ # # # # ]: 0 : if (tfp->session == NULL || tfp->session->core_data == NULL) {
658 : : rc = -EINVAL;
659 : 0 : TFP_DRV_LOG(ERR,
660 : : "Session not created, rc:%s\n",
661 : : strerror(-rc));
662 : 0 : return rc;
663 : : }
664 : :
665 : 0 : *tfs = (struct tf_session *)(tfp->session->core_data);
666 : :
667 : 0 : return rc;
668 : : }
669 : :
670 : : int
671 : 0 : tf_session_get_session(struct tf *tfp,
672 : : struct tf_session **tfs)
673 : : {
674 : : int rc;
675 : : uint16_t fw_fid;
676 : : bool supported = false;
677 : :
678 : 0 : rc = tf_session_get_session_internal(tfp,
679 : : tfs);
680 : : /* Logging done by tf_session_get_session_internal */
681 [ # # ]: 0 : if (rc)
682 : : return rc;
683 : :
684 : : /* As session sharing among functions aka 'individual clients'
685 : : * is supported we have to assure that the client is indeed
686 : : * registered before we get deep in the TruFlow api stack.
687 : : */
688 : 0 : rc = tfp_get_fid(tfp, &fw_fid);
689 [ # # ]: 0 : if (rc) {
690 : 0 : TFP_DRV_LOG(ERR,
691 : : "Internal FID lookup\n, rc:%s\n",
692 : : strerror(-rc));
693 : 0 : return rc;
694 : : }
695 : :
696 : 0 : supported = tf_session_is_fid_supported(*tfs, fw_fid);
697 [ # # ]: 0 : if (!supported) {
698 : 0 : TFP_DRV_LOG
699 : : (ERR,
700 : : "Ctrl channel not registered with session\n, rc:%s\n",
701 : : strerror(-rc));
702 : 0 : return -EINVAL;
703 : : }
704 : :
705 : : return rc;
706 : : }
707 : :
708 : 0 : int tf_session_get(struct tf *tfp,
709 : : struct tf_session **tfs,
710 : : struct tf_dev_info **tfd)
711 : : {
712 : : int rc;
713 : 0 : rc = tf_session_get_session_internal(tfp, tfs);
714 : :
715 : : /* Logging done by tf_session_get_session_internal */
716 [ # # ]: 0 : if (rc)
717 : : return rc;
718 : :
719 : 0 : rc = tf_session_get_device(*tfs, tfd);
720 : :
721 : 0 : return rc;
722 : : }
723 : :
724 : : struct tf_session_client *
725 : 0 : tf_session_get_session_client(struct tf_session *tfs,
726 : : union tf_session_client_id session_client_id)
727 : : {
728 : : struct ll_entry *c_entry;
729 : : struct tf_session_client *client;
730 : :
731 : : /* Skip using the check macro as we just want to return */
732 [ # # ]: 0 : if (tfs == NULL)
733 : : return NULL;
734 : :
735 : 0 : for (c_entry = tfs->client_ll.head;
736 [ # # ]: 0 : c_entry != NULL;
737 : 0 : c_entry = c_entry->next) {
738 : : client = (struct tf_session_client *)c_entry;
739 [ # # ]: 0 : if (client->session_client_id.id == session_client_id.id)
740 : 0 : return client;
741 : : }
742 : :
743 : : return NULL;
744 : : }
745 : :
746 : : struct tf_session_client *
747 : 0 : tf_session_find_session_client_by_name(struct tf_session *tfs,
748 : : const char *ctrl_chan_name)
749 : : {
750 : : struct ll_entry *c_entry;
751 : : struct tf_session_client *client;
752 : :
753 : : /* Skip using the check macro as we just want to return */
754 [ # # ]: 0 : if (tfs == NULL || ctrl_chan_name == NULL)
755 : : return NULL;
756 : :
757 : 0 : for (c_entry = tfs->client_ll.head;
758 [ # # ]: 0 : c_entry != NULL;
759 : 0 : c_entry = c_entry->next) {
760 : : client = (struct tf_session_client *)c_entry;
761 [ # # ]: 0 : if (strncmp(client->ctrl_chan_name,
762 : : ctrl_chan_name,
763 : : TF_SESSION_NAME_MAX) == 0)
764 : 0 : return client;
765 : : }
766 : :
767 : : return NULL;
768 : : }
769 : :
770 : : struct tf_session_client *
771 : 0 : tf_session_find_session_client_by_fid(struct tf_session *tfs,
772 : : uint16_t fid)
773 : : {
774 : : struct ll_entry *c_entry;
775 : : struct tf_session_client *client;
776 : :
777 : : /* Skip using the check macro as we just want to return */
778 [ # # ]: 0 : if (tfs == NULL)
779 : : return NULL;
780 : :
781 : 0 : for (c_entry = tfs->client_ll.head;
782 [ # # ]: 0 : c_entry != NULL;
783 : 0 : c_entry = c_entry->next) {
784 : : client = (struct tf_session_client *)c_entry;
785 [ # # ]: 0 : if (client->fw_fid == fid)
786 : 0 : return client;
787 : : }
788 : :
789 : : return NULL;
790 : : }
791 : :
792 : : int
793 : 0 : tf_session_get_device(struct tf_session *tfs,
794 : : struct tf_dev_info **tfd)
795 : : {
796 : 0 : *tfd = &tfs->dev;
797 : :
798 : 0 : return 0;
799 : : }
800 : :
801 : : int
802 : 0 : tf_session_get_fw_session_id(struct tf *tfp,
803 : : uint8_t *fw_session_id)
804 : : {
805 : : int rc;
806 : 0 : struct tf_session *tfs = NULL;
807 : :
808 : : /* Skip using the check macro as we want to control the error msg */
809 [ # # ]: 0 : if (tfp->session == NULL) {
810 : : rc = -EINVAL;
811 : 0 : TFP_DRV_LOG(ERR,
812 : : "Session not created, rc:%s\n",
813 : : strerror(-rc));
814 : 0 : return rc;
815 : : }
816 : :
817 [ # # ]: 0 : if (fw_session_id == NULL) {
818 : : rc = -EINVAL;
819 : 0 : TFP_DRV_LOG(ERR,
820 : : "Invalid Argument(s), rc:%s\n",
821 : : strerror(-rc));
822 : 0 : return rc;
823 : : }
824 : :
825 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
826 [ # # ]: 0 : if (rc)
827 : : return rc;
828 : :
829 : 0 : *fw_session_id = tfs->session_id.internal.fw_session_id;
830 : :
831 : 0 : return 0;
832 : : }
833 : :
834 : : int
835 : 0 : tf_session_get_session_id(struct tf *tfp,
836 : : union tf_session_id *session_id)
837 : : {
838 : : int rc;
839 : 0 : struct tf_session *tfs = NULL;
840 : :
841 [ # # ]: 0 : if (tfp->session == NULL) {
842 : : rc = -EINVAL;
843 : 0 : TFP_DRV_LOG(ERR,
844 : : "Session not created, rc:%s\n",
845 : : strerror(-rc));
846 : 0 : return rc;
847 : : }
848 : :
849 [ # # ]: 0 : if (session_id == NULL) {
850 : : rc = -EINVAL;
851 : 0 : TFP_DRV_LOG(ERR,
852 : : "Invalid Argument(s), rc:%s\n",
853 : : strerror(-rc));
854 : 0 : return rc;
855 : : }
856 : :
857 : : /* Using internal version as session client may not exist yet */
858 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
859 [ # # ]: 0 : if (rc)
860 : : return rc;
861 : :
862 : 0 : *session_id = tfs->session_id;
863 : :
864 : 0 : return 0;
865 : : }
866 : :
867 : : int
868 : 0 : tf_session_get_em_ext_db(struct tf *tfp,
869 : : void **em_ext_db_handle)
870 : : {
871 : 0 : struct tf_session *tfs = NULL;
872 : : int rc = 0;
873 : :
874 : 0 : *em_ext_db_handle = NULL;
875 : :
876 [ # # ]: 0 : if (tfp == NULL)
877 : : return (-EINVAL);
878 : :
879 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
880 [ # # ]: 0 : if (rc)
881 : : return rc;
882 : :
883 : 0 : *em_ext_db_handle = tfs->em_ext_db_handle;
884 : 0 : return rc;
885 : : }
886 : :
887 : : int
888 : 0 : tf_session_set_em_ext_db(struct tf *tfp,
889 : : void *em_ext_db_handle)
890 : : {
891 : 0 : struct tf_session *tfs = NULL;
892 : : int rc = 0;
893 : :
894 [ # # ]: 0 : if (tfp == NULL)
895 : : return (-EINVAL);
896 : :
897 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
898 [ # # ]: 0 : if (rc)
899 : : return rc;
900 : :
901 : 0 : tfs->em_ext_db_handle = em_ext_db_handle;
902 : 0 : return rc;
903 : : }
904 : :
905 : : int
906 : 0 : tf_session_get_db(struct tf *tfp,
907 : : enum tf_module_type type,
908 : : void **db_handle)
909 : : {
910 : 0 : struct tf_session *tfs = NULL;
911 : : int rc = 0;
912 : :
913 : 0 : *db_handle = NULL;
914 : :
915 [ # # ]: 0 : if (tfp == NULL)
916 : : return (-EINVAL);
917 : :
918 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
919 [ # # ]: 0 : if (rc)
920 : : return rc;
921 : :
922 [ # # # # : 0 : switch (type) {
# ]
923 : 0 : case TF_MODULE_TYPE_IDENTIFIER:
924 [ # # ]: 0 : if (tfs->id_db_handle)
925 : 0 : *db_handle = tfs->id_db_handle;
926 : : else
927 : : rc = -ENOMEM;
928 : : break;
929 : 0 : case TF_MODULE_TYPE_TABLE:
930 [ # # ]: 0 : if (tfs->tbl_db_handle)
931 : 0 : *db_handle = tfs->tbl_db_handle;
932 : : else
933 : : rc = -ENOMEM;
934 : :
935 : : break;
936 : 0 : case TF_MODULE_TYPE_TCAM:
937 [ # # ]: 0 : if (tfs->tcam_db_handle)
938 : 0 : *db_handle = tfs->tcam_db_handle;
939 : : else
940 : : rc = -ENOMEM;
941 : : break;
942 : 0 : case TF_MODULE_TYPE_EM:
943 [ # # ]: 0 : if (tfs->em_db_handle)
944 : 0 : *db_handle = tfs->em_db_handle;
945 : : else
946 : : rc = -ENOMEM;
947 : : break;
948 : : default:
949 : : rc = -EINVAL;
950 : : break;
951 : : }
952 : :
953 : : return rc;
954 : : }
955 : :
956 : : int
957 : 0 : tf_session_set_db(struct tf *tfp,
958 : : enum tf_module_type type,
959 : : void *db_handle)
960 : : {
961 : 0 : struct tf_session *tfs = NULL;
962 : : int rc = 0;
963 : :
964 [ # # ]: 0 : if (tfp == NULL)
965 : : return (-EINVAL);
966 : :
967 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
968 [ # # ]: 0 : if (rc)
969 : : return rc;
970 : :
971 [ # # # # : 0 : switch (type) {
# ]
972 : 0 : case TF_MODULE_TYPE_IDENTIFIER:
973 : 0 : tfs->id_db_handle = db_handle;
974 : 0 : break;
975 : 0 : case TF_MODULE_TYPE_TABLE:
976 : 0 : tfs->tbl_db_handle = db_handle;
977 : 0 : break;
978 : 0 : case TF_MODULE_TYPE_TCAM:
979 : 0 : tfs->tcam_db_handle = db_handle;
980 : 0 : break;
981 : 0 : case TF_MODULE_TYPE_EM:
982 : 0 : tfs->em_db_handle = db_handle;
983 : 0 : break;
984 : : default:
985 : : rc = -EINVAL;
986 : : break;
987 : : }
988 : :
989 : : return rc;
990 : : }
991 : :
992 : : int
993 : 0 : tf_session_get_tcam_shared_db(struct tf *tfp,
994 : : void **tcam_shared_db_handle)
995 : : {
996 : 0 : struct tf_session *tfs = NULL;
997 : : int rc = 0;
998 : :
999 : 0 : *tcam_shared_db_handle = NULL;
1000 : :
1001 [ # # ]: 0 : if (tfp == NULL)
1002 : : return (-EINVAL);
1003 : :
1004 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1005 [ # # ]: 0 : if (rc)
1006 : : return rc;
1007 : :
1008 : 0 : *tcam_shared_db_handle = tfs->tcam_shared_db_handle;
1009 : 0 : return rc;
1010 : : }
1011 : :
1012 : : int
1013 : 0 : tf_session_set_tcam_shared_db(struct tf *tfp,
1014 : : void *tcam_shared_db_handle)
1015 : : {
1016 : 0 : struct tf_session *tfs = NULL;
1017 : : int rc = 0;
1018 : :
1019 [ # # ]: 0 : if (tfp == NULL)
1020 : : return (-EINVAL);
1021 : :
1022 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1023 [ # # ]: 0 : if (rc)
1024 : : return rc;
1025 : :
1026 : 0 : tfs->tcam_shared_db_handle = tcam_shared_db_handle;
1027 : 0 : return rc;
1028 : : }
1029 : :
1030 : : int
1031 : 0 : tf_session_get_sram_db(struct tf *tfp,
1032 : : void **sram_handle)
1033 : : {
1034 : 0 : struct tf_session *tfs = NULL;
1035 : : int rc = 0;
1036 : :
1037 : 0 : *sram_handle = NULL;
1038 : :
1039 [ # # ]: 0 : if (tfp == NULL)
1040 : : return (-EINVAL);
1041 : :
1042 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1043 [ # # ]: 0 : if (rc)
1044 : : return rc;
1045 : :
1046 : 0 : *sram_handle = tfs->sram_handle;
1047 : 0 : return rc;
1048 : : }
1049 : :
1050 : : int
1051 : 0 : tf_session_set_sram_db(struct tf *tfp,
1052 : : void *sram_handle)
1053 : : {
1054 : 0 : struct tf_session *tfs = NULL;
1055 : : int rc = 0;
1056 : :
1057 [ # # ]: 0 : if (tfp == NULL)
1058 : : return (-EINVAL);
1059 : :
1060 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1061 [ # # ]: 0 : if (rc)
1062 : : return rc;
1063 : :
1064 : 0 : tfs->sram_handle = sram_handle;
1065 : 0 : return rc;
1066 : : }
1067 : :
1068 : : int
1069 : 0 : tf_session_get_global_db(struct tf *tfp,
1070 : : void **global_handle)
1071 : : {
1072 : 0 : struct tf_session *tfs = NULL;
1073 : : int rc = 0;
1074 : :
1075 : 0 : *global_handle = NULL;
1076 : :
1077 [ # # ]: 0 : if (tfp == NULL)
1078 : : return (-EINVAL);
1079 : :
1080 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1081 [ # # ]: 0 : if (rc)
1082 : : return rc;
1083 : :
1084 : 0 : *global_handle = tfs->global_db_handle;
1085 : 0 : return rc;
1086 : : }
1087 : :
1088 : : int
1089 : 0 : tf_session_set_global_db(struct tf *tfp,
1090 : : void *global_handle)
1091 : : {
1092 : 0 : struct tf_session *tfs = NULL;
1093 : : int rc = 0;
1094 : :
1095 [ # # ]: 0 : if (tfp == NULL)
1096 : : return (-EINVAL);
1097 : :
1098 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1099 [ # # ]: 0 : if (rc)
1100 : : return rc;
1101 : :
1102 : 0 : tfs->global_db_handle = global_handle;
1103 : 0 : return rc;
1104 : : }
1105 : :
1106 : : int
1107 : 0 : tf_session_get_if_tbl_db(struct tf *tfp,
1108 : : void **if_tbl_handle)
1109 : : {
1110 : 0 : struct tf_session *tfs = NULL;
1111 : : int rc = 0;
1112 : :
1113 : 0 : *if_tbl_handle = NULL;
1114 : :
1115 [ # # ]: 0 : if (tfp == NULL)
1116 : : return (-EINVAL);
1117 : :
1118 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1119 [ # # ]: 0 : if (rc)
1120 : : return rc;
1121 : :
1122 : 0 : *if_tbl_handle = tfs->if_tbl_db_handle;
1123 : 0 : return rc;
1124 : : }
1125 : :
1126 : : int
1127 : 0 : tf_session_set_if_tbl_db(struct tf *tfp,
1128 : : void *if_tbl_handle)
1129 : : {
1130 : 0 : struct tf_session *tfs = NULL;
1131 : : int rc = 0;
1132 : :
1133 [ # # ]: 0 : if (tfp == NULL)
1134 : : return (-EINVAL);
1135 : :
1136 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
1137 [ # # ]: 0 : if (rc)
1138 : : return rc;
1139 : :
1140 : 0 : tfs->if_tbl_db_handle = if_tbl_handle;
1141 : 0 : return rc;
1142 : : }
1143 : :
1144 : : int
1145 : 0 : tf_session_set_hotup_state(struct tf *tfp,
1146 : : struct tf_set_session_hotup_state_parms *parms)
1147 : : {
1148 : : int rc = 0;
1149 : 0 : struct tf_session *tfs = NULL;
1150 : :
1151 : 0 : rc = tf_session_get_session(tfp, &tfs);
1152 [ # # ]: 0 : if (rc) {
1153 : 0 : TFP_DRV_LOG(ERR,
1154 : : "Session lookup failed, rc:%s\n",
1155 : : strerror(-rc));
1156 : 0 : return rc;
1157 : : }
1158 : :
1159 [ # # ]: 0 : if (!tf_session_is_shared_session(tfs)) {
1160 : : rc = -EINVAL;
1161 : 0 : TFP_DRV_LOG(ERR,
1162 : : "Only shared session able to set state, rc:%s\n",
1163 : : strerror(-rc));
1164 : 0 : return rc;
1165 : : }
1166 : :
1167 : 0 : rc = tf_msg_session_set_hotup_state(tfp, parms->state);
1168 [ # # ]: 0 : if (rc) {
1169 : : /* Log error */
1170 : 0 : TFP_DRV_LOG(ERR,
1171 : : "Set session hot upgrade state failed, rc:%s\n",
1172 : : strerror(-rc));
1173 : : }
1174 : :
1175 : : return rc;
1176 : : }
1177 : :
1178 : : int
1179 : 0 : tf_session_get_hotup_state(struct tf *tfp,
1180 : : struct tf_get_session_hotup_state_parms *parms)
1181 : : {
1182 : : int rc = 0;
1183 : 0 : struct tf_session *tfs = NULL;
1184 : :
1185 : 0 : rc = tf_session_get_session(tfp, &tfs);
1186 [ # # ]: 0 : if (rc) {
1187 : 0 : TFP_DRV_LOG(ERR,
1188 : : "Session lookup failed, rc:%s\n",
1189 : : strerror(-rc));
1190 : 0 : return rc;
1191 : : }
1192 : :
1193 [ # # ]: 0 : if (!tf_session_is_shared_session(tfs)) {
1194 : : rc = -EINVAL;
1195 : 0 : TFP_DRV_LOG(ERR,
1196 : : "Only shared session able to get state, rc:%s\n",
1197 : : strerror(-rc));
1198 : 0 : return rc;
1199 : : }
1200 : :
1201 : 0 : rc = tf_msg_session_get_hotup_state(tfp, &parms->state, &parms->ref_cnt);
1202 [ # # ]: 0 : if (rc) {
1203 : : /* Log error */
1204 : 0 : TFP_DRV_LOG(ERR,
1205 : : "Get session hot upgrade state failed, rc:%s\n",
1206 : : strerror(-rc));
1207 : : }
1208 : :
1209 : : return rc;
1210 : : }
|