net/bnxt: add initial TruFlow core session close
[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
16 int
17 tf_open_session(struct tf                    *tfp,
18                 struct tf_open_session_parms *parms)
19 {
20         int rc;
21         struct tf_session *session;
22         struct tfp_calloc_parms alloc_parms;
23         unsigned int domain, bus, slot, device;
24         uint8_t fw_session_id;
25
26         if (tfp == NULL || parms == NULL)
27                 return -EINVAL;
28
29         /* Filter out any non-supported device types on the Core
30          * side. It is assumed that the Firmware will be supported if
31          * firmware open session succeeds.
32          */
33         if (parms->device_type != TF_DEVICE_TYPE_WH)
34                 return -ENOTSUP;
35
36         /* Build the beginning of session_id */
37         rc = sscanf(parms->ctrl_chan_name,
38                     "%x:%x:%x.%d",
39                     &domain,
40                     &bus,
41                     &slot,
42                     &device);
43         if (rc != 4) {
44                 PMD_DRV_LOG(ERR,
45                             "Failed to scan device ctrl_chan_name\n");
46                 return -EINVAL;
47         }
48
49         /* open FW session and get a new session_id */
50         rc = tf_msg_session_open(tfp,
51                                  parms->ctrl_chan_name,
52                                  &fw_session_id);
53         if (rc) {
54                 /* Log error */
55                 if (rc == -EEXIST)
56                         PMD_DRV_LOG(ERR,
57                                     "Session is already open, rc:%d\n",
58                                     rc);
59                 else
60                         PMD_DRV_LOG(ERR,
61                                     "Open message send failed, rc:%d\n",
62                                     rc);
63
64                 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
65                 return rc;
66         }
67
68         /* Allocate session */
69         alloc_parms.nitems = 1;
70         alloc_parms.size = sizeof(struct tf_session_info);
71         alloc_parms.alignment = 0;
72         rc = tfp_calloc(&alloc_parms);
73         if (rc) {
74                 /* Log error */
75                 PMD_DRV_LOG(ERR,
76                             "Failed to allocate session info, rc:%d\n",
77                             rc);
78                 goto cleanup;
79         }
80
81         tfp->session = (struct tf_session_info *)alloc_parms.mem_va;
82
83         /* Allocate core data for the session */
84         alloc_parms.nitems = 1;
85         alloc_parms.size = sizeof(struct tf_session);
86         alloc_parms.alignment = 0;
87         rc = tfp_calloc(&alloc_parms);
88         if (rc) {
89                 /* Log error */
90                 PMD_DRV_LOG(ERR,
91                             "Failed to allocate session data, rc:%d\n",
92                             rc);
93                 goto cleanup;
94         }
95
96         tfp->session->core_data = alloc_parms.mem_va;
97
98         session = (struct tf_session *)tfp->session->core_data;
99         tfp_memcpy(session->ctrl_chan_name,
100                    parms->ctrl_chan_name,
101                    TF_SESSION_NAME_MAX);
102
103         /* Initialize Session */
104         session->device_type = parms->device_type;
105
106         /* Construct the Session ID */
107         session->session_id.internal.domain = domain;
108         session->session_id.internal.bus = bus;
109         session->session_id.internal.device = device;
110         session->session_id.internal.fw_session_id = fw_session_id;
111
112         rc = tf_msg_session_qcfg(tfp);
113         if (rc) {
114                 /* Log error */
115                 PMD_DRV_LOG(ERR,
116                             "Query config message send failed, rc:%d\n",
117                             rc);
118                 goto cleanup_close;
119         }
120
121         session->ref_count++;
122
123         /* Return session ID */
124         parms->session_id = session->session_id;
125
126         PMD_DRV_LOG(INFO,
127                     "Session created, session_id:%d\n",
128                     parms->session_id.id);
129
130         PMD_DRV_LOG(INFO,
131                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
132                     parms->session_id.internal.domain,
133                     parms->session_id.internal.bus,
134                     parms->session_id.internal.device,
135                     parms->session_id.internal.fw_session_id);
136
137         return 0;
138
139  cleanup:
140         tfp_free(tfp->session->core_data);
141         tfp_free(tfp->session);
142         tfp->session = NULL;
143         return rc;
144
145  cleanup_close:
146         tf_close_session(tfp);
147         return -EINVAL;
148 }
149
150 int
151 tf_attach_session(struct tf *tfp __rte_unused,
152                   struct tf_attach_session_parms *parms __rte_unused)
153 {
154 #if (TF_SHARED == 1)
155         int rc;
156
157         if (tfp == NULL)
158                 return -EINVAL;
159
160         /* - Open the shared memory for the attach_chan_name
161          * - Point to the shared session for this Device instance
162          * - Check that session is valid
163          * - Attach to the firmware so it can record there is more
164          *   than one client of the session.
165          */
166
167         if (tfp->session) {
168                 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
169                         rc = tf_msg_session_attach(tfp,
170                                                    parms->ctrl_chan_name,
171                                                    parms->session_id);
172                 }
173         }
174 #endif /* TF_SHARED */
175         return -1;
176 }
177
178 int
179 tf_close_session(struct tf *tfp)
180 {
181         int rc;
182         int rc_close = 0;
183         struct tf_session *tfs;
184         union tf_session_id session_id;
185
186         if (tfp == NULL || tfp->session == NULL)
187                 return -EINVAL;
188
189         tfs = (struct tf_session *)(tfp->session->core_data);
190
191         if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
192                 rc = tf_msg_session_close(tfp);
193                 if (rc) {
194                         /* Log error */
195                         PMD_DRV_LOG(ERR,
196                                     "Message send failed, rc:%d\n",
197                                     rc);
198                 }
199
200                 /* Update the ref_count */
201                 tfs->ref_count--;
202         }
203
204         session_id = tfs->session_id;
205
206         /* Final cleanup as we're last user of the session */
207         if (tfs->ref_count == 0) {
208                 tfp_free(tfp->session->core_data);
209                 tfp_free(tfp->session);
210                 tfp->session = NULL;
211         }
212
213         PMD_DRV_LOG(INFO,
214                     "Session closed, session_id:%d\n",
215                     session_id.id);
216
217         PMD_DRV_LOG(INFO,
218                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
219                     session_id.internal.domain,
220                     session_id.internal.bus,
221                     session_id.internal.device,
222                     session_id.internal.fw_session_id);
223
224         return rc_close;
225 }