9ff81b047f64dd348412be6c92b414aee9d4f8c3
[dpdk.git] / drivers / net / bnxt / tf_core / tf_session.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7
8 #include <rte_common.h>
9
10 #include "tf_session.h"
11 #include "tf_common.h"
12 #include "tf_msg.h"
13 #include "tfp.h"
14
15 int
16 tf_session_open_session(struct tf *tfp,
17                         struct tf_session_open_session_parms *parms)
18 {
19         int rc;
20         struct tf_session *session = NULL;
21         struct tfp_calloc_parms cparms;
22         uint8_t fw_session_id;
23         union tf_session_id *session_id;
24
25         TF_CHECK_PARMS2(tfp, parms);
26
27         /* Open FW session and get a new session_id */
28         rc = tf_msg_session_open(tfp,
29                                  parms->open_cfg->ctrl_chan_name,
30                                  &fw_session_id);
31         if (rc) {
32                 /* Log error */
33                 if (rc == -EEXIST)
34                         TFP_DRV_LOG(ERR,
35                                     "Session is already open, rc:%s\n",
36                                     strerror(-rc));
37                 else
38                         TFP_DRV_LOG(ERR,
39                                     "Open message send failed, rc:%s\n",
40                                     strerror(-rc));
41
42                 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
43                 return rc;
44         }
45
46         /* Allocate session */
47         cparms.nitems = 1;
48         cparms.size = sizeof(struct tf_session_info);
49         cparms.alignment = 0;
50         rc = tfp_calloc(&cparms);
51         if (rc) {
52                 /* Log error */
53                 TFP_DRV_LOG(ERR,
54                             "Failed to allocate session info, rc:%s\n",
55                             strerror(-rc));
56                 goto cleanup;
57         }
58         tfp->session = (struct tf_session_info *)cparms.mem_va;
59
60         /* Allocate core data for the session */
61         cparms.nitems = 1;
62         cparms.size = sizeof(struct tf_session);
63         cparms.alignment = 0;
64         rc = tfp_calloc(&cparms);
65         if (rc) {
66                 /* Log error */
67                 TFP_DRV_LOG(ERR,
68                             "Failed to allocate session data, rc:%s\n",
69                             strerror(-rc));
70                 goto cleanup;
71         }
72         tfp->session->core_data = cparms.mem_va;
73         session_id = &parms->open_cfg->session_id;
74
75         /* Update Session Info, which is what is visible to the caller */
76         tfp->session->ver.major = 0;
77         tfp->session->ver.minor = 0;
78         tfp->session->ver.update = 0;
79
80         tfp->session->session_id.internal.domain = session_id->internal.domain;
81         tfp->session->session_id.internal.bus = session_id->internal.bus;
82         tfp->session->session_id.internal.device = session_id->internal.device;
83         tfp->session->session_id.internal.fw_session_id = fw_session_id;
84
85         /* Initialize Session and Device, which is private */
86         session = (struct tf_session *)tfp->session->core_data;
87         session->ver.major = 0;
88         session->ver.minor = 0;
89         session->ver.update = 0;
90
91         session->session_id.internal.domain = session_id->internal.domain;
92         session->session_id.internal.bus = session_id->internal.bus;
93         session->session_id.internal.device = session_id->internal.device;
94         session->session_id.internal.fw_session_id = fw_session_id;
95         /* Return the allocated fw session id */
96         session_id->internal.fw_session_id = fw_session_id;
97
98         session->shadow_copy = parms->open_cfg->shadow_copy;
99
100         tfp_memcpy(session->ctrl_chan_name,
101                    parms->open_cfg->ctrl_chan_name,
102                    TF_SESSION_NAME_MAX);
103
104         rc = tf_dev_bind(tfp,
105                          parms->open_cfg->device_type,
106                          session->shadow_copy,
107                          &parms->open_cfg->resources,
108                          &session->dev);
109         /* Logging handled by dev_bind */
110         if (rc)
111                 return rc;
112
113         session->ref_count++;
114
115         return 0;
116
117  cleanup:
118         tfp_free(tfp->session->core_data);
119         tfp_free(tfp->session);
120         tfp->session = NULL;
121         return rc;
122 }
123
124 int
125 tf_session_attach_session(struct tf *tfp __rte_unused,
126                           struct tf_session_attach_session_parms *parms __rte_unused)
127 {
128         int rc = -EOPNOTSUPP;
129
130         TF_CHECK_PARMS2(tfp, parms);
131
132         TFP_DRV_LOG(ERR,
133                     "Attach not yet supported, rc:%s\n",
134                     strerror(-rc));
135         return rc;
136 }
137
138 int
139 tf_session_close_session(struct tf *tfp,
140                          struct tf_session_close_session_parms *parms)
141 {
142         int rc;
143         struct tf_session *tfs = NULL;
144         struct tf_dev_info *tfd = NULL;
145
146         TF_CHECK_PARMS2(tfp, parms);
147
148         rc = tf_session_get_session(tfp, &tfs);
149         if (rc) {
150                 TFP_DRV_LOG(ERR,
151                             "Session lookup failed, rc:%s\n",
152                             strerror(-rc));
153                 return rc;
154         }
155
156         if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
157                 rc = -EINVAL;
158                 TFP_DRV_LOG(ERR,
159                             "Invalid session id, unable to close, rc:%s\n",
160                             strerror(-rc));
161                 return rc;
162         }
163
164         tfs->ref_count--;
165
166         /* Record the session we're closing so the caller knows the
167          * details.
168          */
169         *parms->session_id = tfs->session_id;
170
171         rc = tf_session_get_device(tfs, &tfd);
172         if (rc) {
173                 TFP_DRV_LOG(ERR,
174                             "Device lookup failed, rc:%s\n",
175                             strerror(-rc));
176                 return rc;
177         }
178
179         if (tfs->ref_count > 0) {
180                 /* In case we're attached only the session client gets
181                  * closed.
182                  */
183                 rc = tf_msg_session_close(tfp);
184                 if (rc) {
185                         /* Log error */
186                         TFP_DRV_LOG(ERR,
187                                     "FW Session close failed, rc:%s\n",
188                                     strerror(-rc));
189                 }
190
191                 return 0;
192         }
193
194         /* Final cleanup as we're last user of the session */
195
196         /* Unbind the device */
197         rc = tf_dev_unbind(tfp, tfd);
198         if (rc) {
199                 /* Log error */
200                 TFP_DRV_LOG(ERR,
201                             "Device unbind failed, rc:%s\n",
202                             strerror(-rc));
203         }
204
205         /* In case we're attached only the session client gets closed */
206         rc = tf_msg_session_close(tfp);
207         if (rc) {
208                 /* Log error */
209                 TFP_DRV_LOG(ERR,
210                             "FW Session close failed, rc:%s\n",
211                             strerror(-rc));
212         }
213
214         tfp_free(tfp->session->core_data);
215         tfp_free(tfp->session);
216         tfp->session = NULL;
217
218         return 0;
219 }
220
221 int
222 tf_session_get_session(struct tf *tfp,
223                        struct tf_session **tfs)
224 {
225         int rc;
226
227         if (tfp->session == NULL || tfp->session->core_data == NULL) {
228                 rc = -EINVAL;
229                 TFP_DRV_LOG(ERR,
230                             "Session not created, rc:%s\n",
231                             strerror(-rc));
232                 return rc;
233         }
234
235         *tfs = (struct tf_session *)(tfp->session->core_data);
236
237         return 0;
238 }
239
240 int
241 tf_session_get_device(struct tf_session *tfs,
242                       struct tf_dev_info **tfd)
243 {
244         *tfd = &tfs->dev;
245
246         return 0;
247 }
248
249 int
250 tf_session_get_fw_session_id(struct tf *tfp,
251                              uint8_t *fw_session_id)
252 {
253         int rc;
254         struct tf_session *tfs = NULL;
255
256         if (tfp->session == NULL) {
257                 rc = -EINVAL;
258                 TFP_DRV_LOG(ERR,
259                             "Session not created, rc:%s\n",
260                             strerror(-rc));
261                 return rc;
262         }
263
264         rc = tf_session_get_session(tfp, &tfs);
265         if (rc)
266                 return rc;
267
268         *fw_session_id = tfs->session_id.internal.fw_session_id;
269
270         return 0;
271 }