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