1
2
3
4
5#include <string.h>
6
7#include <rte_atomic.h>
8#include <rte_common.h>
9#include <rte_cycles.h>
10#include <rte_io.h>
11#include <rte_spinlock.h>
12
13#include "octeontx_mbox.h"
14
15
16#define MBOX_WAIT_TIME_SEC 3
17#define MAX_RAM_MBOX_LEN ((SSOW_BAR4_LEN >> 1) - 8 )
18
19
20enum {
21 MBOX_CHAN_STATE_REQ = 1,
22 MBOX_CHAN_STATE_RES = 0,
23};
24
25
26enum {
27 MBOX_RET_SUCCESS,
28 MBOX_RET_INVALID,
29 MBOX_RET_INTERNAL_ERR,
30};
31
32struct mbox {
33 int init_once;
34 uint8_t ready;
35 uint8_t *ram_mbox_base;
36 uint8_t *reg;
37 uint16_t tag_own;
38 uint16_t domain;
39 rte_spinlock_t lock;
40};
41
42static struct mbox octeontx_mbox;
43
44
45
46
47
48
49struct mbox_ram_hdr {
50 union {
51 uint64_t u64;
52 struct {
53 uint8_t chan_state : 1;
54 uint8_t coproc : 7;
55 uint8_t msg;
56 uint8_t vfid;
57 uint8_t res_code;
58 uint16_t tag;
59 uint16_t len;
60 };
61 };
62};
63
64
65struct mbox_intf_ver {
66 uint32_t platform:12;
67 uint32_t major:10;
68 uint32_t minor:10;
69};
70
71RTE_LOG_REGISTER(octeontx_logtype_mbox, pmd.octeontx.mbox, NOTICE);
72
73static inline void
74mbox_msgcpy(volatile uint8_t *d, volatile const uint8_t *s, uint16_t size)
75{
76 uint16_t i;
77
78 for (i = 0; i < size; i++)
79 d[i] = s[i];
80}
81
82static inline void
83mbox_send_request(struct mbox *m, struct octeontx_mbox_hdr *hdr,
84 const void *txmsg, uint16_t txsize)
85{
86 struct mbox_ram_hdr old_hdr;
87 struct mbox_ram_hdr new_hdr = { {0} };
88 uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
89 uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
90
91
92
93
94
95
96 old_hdr.u64 = rte_read64(ram_mbox_hdr);
97 m->tag_own = (old_hdr.tag + 2) & (~0x1ul);
98
99
100 if (txmsg)
101 mbox_msgcpy(ram_mbox_msg, txmsg, txsize);
102
103
104 new_hdr.chan_state = MBOX_CHAN_STATE_REQ;
105 new_hdr.coproc = hdr->coproc;
106 new_hdr.msg = hdr->msg;
107 new_hdr.vfid = hdr->vfid;
108 new_hdr.tag = m->tag_own;
109 new_hdr.len = txsize;
110
111
112 rte_write64(new_hdr.u64, ram_mbox_hdr);
113 rte_smp_wmb();
114
115 rte_write64(0, m->reg);
116}
117
118static inline int
119mbox_wait_response(struct mbox *m, struct octeontx_mbox_hdr *hdr,
120 void *rxmsg, uint16_t rxsize)
121{
122 int res = 0, wait;
123 uint16_t len;
124 struct mbox_ram_hdr rx_hdr;
125 uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
126 uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
127
128
129 wait = MBOX_WAIT_TIME_SEC * 1000 * 10;
130 while (wait > 0) {
131 rte_delay_us(100);
132 rx_hdr.u64 = rte_read64(ram_mbox_hdr);
133 if (rx_hdr.chan_state == MBOX_CHAN_STATE_RES)
134 break;
135 --wait;
136 }
137
138 hdr->res_code = rx_hdr.res_code;
139 m->tag_own++;
140
141
142 if (wait <= 0) {
143 res = -ETIMEDOUT;
144 goto error;
145 }
146
147
148 if (m->tag_own != rx_hdr.tag) {
149 res = -EINVAL;
150 goto error;
151 }
152
153
154 if (rx_hdr.res_code != MBOX_RET_SUCCESS) {
155 res = -EBADMSG;
156 goto error;
157 }
158
159 len = RTE_MIN(rx_hdr.len, rxsize);
160 if (rxmsg)
161 mbox_msgcpy(rxmsg, ram_mbox_msg, len);
162
163 return len;
164
165error:
166 mbox_log_err("Failed to send mbox(%d/%d) coproc=%d msg=%d ret=(%d,%d)",
167 m->tag_own, rx_hdr.tag, hdr->coproc, hdr->msg, res,
168 hdr->res_code);
169 return res;
170}
171
172static inline int
173mbox_send(struct mbox *m, struct octeontx_mbox_hdr *hdr, const void *txmsg,
174 uint16_t txsize, void *rxmsg, uint16_t rxsize)
175{
176 int res = -EINVAL;
177
178 if (m->init_once == 0 || hdr == NULL ||
179 txsize > MAX_RAM_MBOX_LEN || rxsize > MAX_RAM_MBOX_LEN) {
180 mbox_log_err("Invalid init_once=%d hdr=%p txsz=%d rxsz=%d",
181 m->init_once, hdr, txsize, rxsize);
182 return res;
183 }
184
185 rte_spinlock_lock(&m->lock);
186
187 mbox_send_request(m, hdr, txmsg, txsize);
188 res = mbox_wait_response(m, hdr, rxmsg, rxsize);
189
190 rte_spinlock_unlock(&m->lock);
191 return res;
192}
193
194int
195octeontx_mbox_set_ram_mbox_base(uint8_t *ram_mbox_base, uint16_t domain)
196{
197 struct mbox *m = &octeontx_mbox;
198
199 if (m->init_once)
200 return -EALREADY;
201
202 if (ram_mbox_base == NULL) {
203 mbox_log_err("Invalid ram_mbox_base=%p", ram_mbox_base);
204 return -EINVAL;
205 }
206
207 m->ram_mbox_base = ram_mbox_base;
208
209 if (m->reg != NULL) {
210 rte_spinlock_init(&m->lock);
211 m->init_once = 1;
212 m->domain = domain;
213 }
214
215 return 0;
216}
217
218int
219octeontx_mbox_set_reg(uint8_t *reg, uint16_t domain)
220{
221 struct mbox *m = &octeontx_mbox;
222
223 if (m->init_once)
224 return -EALREADY;
225
226 if (reg == NULL) {
227 mbox_log_err("Invalid reg=%p", reg);
228 return -EINVAL;
229 }
230
231 m->reg = reg;
232
233 if (m->ram_mbox_base != NULL) {
234 rte_spinlock_init(&m->lock);
235 m->init_once = 1;
236 m->domain = domain;
237 }
238
239 return 0;
240}
241
242int
243octeontx_mbox_send(struct octeontx_mbox_hdr *hdr, void *txdata,
244 uint16_t txlen, void *rxdata, uint16_t rxlen)
245{
246 struct mbox *m = &octeontx_mbox;
247
248 RTE_BUILD_BUG_ON(sizeof(struct mbox_ram_hdr) != 8);
249 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
250 return -EINVAL;
251
252 return mbox_send(m, hdr, txdata, txlen, rxdata, rxlen);
253}
254
255static int
256octeontx_start_domain(void)
257{
258 struct octeontx_mbox_hdr hdr = {0};
259 int result = -EINVAL;
260
261 hdr.coproc = NO_COPROC;
262 hdr.msg = RM_START_APP;
263
264 result = octeontx_mbox_send(&hdr, NULL, 0, NULL, 0);
265 if (result != 0) {
266 mbox_log_err("Could not start domain. Err=%d. FuncErr=%d\n",
267 result, hdr.res_code);
268 result = -EINVAL;
269 }
270
271 return result;
272}
273
274static int
275octeontx_check_mbox_version(struct mbox_intf_ver *app_intf_ver,
276 struct mbox_intf_ver *intf_ver)
277{
278 struct mbox_intf_ver kernel_intf_ver = {0};
279 struct octeontx_mbox_hdr hdr = {0};
280 int result = 0;
281
282
283 hdr.coproc = NO_COPROC;
284 hdr.msg = RM_INTERFACE_VERSION;
285
286 result = octeontx_mbox_send(&hdr, app_intf_ver,
287 sizeof(struct mbox_intf_ver),
288 &kernel_intf_ver, sizeof(kernel_intf_ver));
289 if (result != sizeof(kernel_intf_ver)) {
290 mbox_log_err("Could not send interface version. Err=%d. FuncErr=%d\n",
291 result, hdr.res_code);
292 result = -EINVAL;
293 }
294
295 if (intf_ver)
296 *intf_ver = kernel_intf_ver;
297
298 if (app_intf_ver->platform != kernel_intf_ver.platform ||
299 app_intf_ver->major != kernel_intf_ver.major ||
300 app_intf_ver->minor != kernel_intf_ver.minor)
301 result = -EINVAL;
302
303 return result;
304}
305
306int
307octeontx_mbox_init(void)
308{
309 struct mbox_intf_ver MBOX_INTERFACE_VERSION = {
310 .platform = 0x01,
311 .major = 0x01,
312 .minor = 0x03
313 };
314 struct mbox_intf_ver rm_intf_ver = {0};
315 struct mbox *m = &octeontx_mbox;
316 int ret;
317
318 if (m->ready)
319 return 0;
320
321 ret = octeontx_start_domain();
322 if (ret < 0) {
323 m->init_once = 0;
324 return ret;
325 }
326
327 ret = octeontx_check_mbox_version(&MBOX_INTERFACE_VERSION,
328 &rm_intf_ver);
329 if (ret < 0) {
330 mbox_log_err("MBOX version: Kernel(%d.%d.%d) != DPDK(%d.%d.%d)",
331 rm_intf_ver.platform, rm_intf_ver.major,
332 rm_intf_ver.minor, MBOX_INTERFACE_VERSION.platform,
333 MBOX_INTERFACE_VERSION.major,
334 MBOX_INTERFACE_VERSION.minor);
335 m->init_once = 0;
336 return -EINVAL;
337 }
338
339 m->ready = 1;
340 rte_mb();
341
342 return 0;
343}
344
345uint16_t
346octeontx_get_global_domain(void)
347{
348 struct mbox *m = &octeontx_mbox;
349
350 return m->domain;
351}
352