1
2
3
4
5#include <errno.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include <rte_atomic.h>
11#include <rte_cycles.h>
12#include <rte_malloc.h>
13
14#include "otx2_mbox.h"
15#include "otx2_dev.h"
16
17#define RVU_AF_AFPF_MBOX0 (0x02000)
18#define RVU_AF_AFPF_MBOX1 (0x02008)
19
20#define RVU_PF_PFAF_MBOX0 (0xC00)
21#define RVU_PF_PFAF_MBOX1 (0xC08)
22
23#define RVU_PF_VFX_PFVF_MBOX0 (0x0000)
24#define RVU_PF_VFX_PFVF_MBOX1 (0x0008)
25
26#define RVU_VF_VFPF_MBOX0 (0x0000)
27#define RVU_VF_VFPF_MBOX1 (0x0008)
28
29static inline uint16_t
30msgs_offset(void)
31{
32 return RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
33}
34
35void
36otx2_mbox_fini(struct otx2_mbox *mbox)
37{
38 mbox->reg_base = 0;
39 mbox->hwbase = 0;
40 rte_free(mbox->dev);
41 mbox->dev = NULL;
42}
43
44void
45otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
46{
47 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
48 struct mbox_hdr *tx_hdr =
49 (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->tx_start);
50 struct mbox_hdr *rx_hdr =
51 (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
52
53 rte_spinlock_lock(&mdev->mbox_lock);
54 mdev->msg_size = 0;
55 mdev->rsp_size = 0;
56 tx_hdr->msg_size = 0;
57 tx_hdr->num_msgs = 0;
58 rx_hdr->msg_size = 0;
59 rx_hdr->num_msgs = 0;
60 rte_spinlock_unlock(&mdev->mbox_lock);
61}
62
63int
64otx2_mbox_init(struct otx2_mbox *mbox, uintptr_t hwbase, uintptr_t reg_base,
65 int direction, int ndevs, uint64_t intr_offset)
66{
67 struct otx2_mbox_dev *mdev;
68 int devid;
69
70 mbox->intr_offset = intr_offset;
71 mbox->reg_base = reg_base;
72 mbox->hwbase = hwbase;
73
74 switch (direction) {
75 case MBOX_DIR_AFPF:
76 case MBOX_DIR_PFVF:
77 mbox->tx_start = MBOX_DOWN_TX_START;
78 mbox->rx_start = MBOX_DOWN_RX_START;
79 mbox->tx_size = MBOX_DOWN_TX_SIZE;
80 mbox->rx_size = MBOX_DOWN_RX_SIZE;
81 break;
82 case MBOX_DIR_PFAF:
83 case MBOX_DIR_VFPF:
84 mbox->tx_start = MBOX_DOWN_RX_START;
85 mbox->rx_start = MBOX_DOWN_TX_START;
86 mbox->tx_size = MBOX_DOWN_RX_SIZE;
87 mbox->rx_size = MBOX_DOWN_TX_SIZE;
88 break;
89 case MBOX_DIR_AFPF_UP:
90 case MBOX_DIR_PFVF_UP:
91 mbox->tx_start = MBOX_UP_TX_START;
92 mbox->rx_start = MBOX_UP_RX_START;
93 mbox->tx_size = MBOX_UP_TX_SIZE;
94 mbox->rx_size = MBOX_UP_RX_SIZE;
95 break;
96 case MBOX_DIR_PFAF_UP:
97 case MBOX_DIR_VFPF_UP:
98 mbox->tx_start = MBOX_UP_RX_START;
99 mbox->rx_start = MBOX_UP_TX_START;
100 mbox->tx_size = MBOX_UP_RX_SIZE;
101 mbox->rx_size = MBOX_UP_TX_SIZE;
102 break;
103 default:
104 return -ENODEV;
105 }
106
107 switch (direction) {
108 case MBOX_DIR_AFPF:
109 case MBOX_DIR_AFPF_UP:
110 mbox->trigger = RVU_AF_AFPF_MBOX0;
111 mbox->tr_shift = 4;
112 break;
113 case MBOX_DIR_PFAF:
114 case MBOX_DIR_PFAF_UP:
115 mbox->trigger = RVU_PF_PFAF_MBOX1;
116 mbox->tr_shift = 0;
117 break;
118 case MBOX_DIR_PFVF:
119 case MBOX_DIR_PFVF_UP:
120 mbox->trigger = RVU_PF_VFX_PFVF_MBOX0;
121 mbox->tr_shift = 12;
122 break;
123 case MBOX_DIR_VFPF:
124 case MBOX_DIR_VFPF_UP:
125 mbox->trigger = RVU_VF_VFPF_MBOX1;
126 mbox->tr_shift = 0;
127 break;
128 default:
129 return -ENODEV;
130 }
131
132 mbox->dev = rte_zmalloc("mbox dev",
133 ndevs * sizeof(struct otx2_mbox_dev),
134 OTX2_ALIGN);
135 if (!mbox->dev) {
136 otx2_mbox_fini(mbox);
137 return -ENOMEM;
138 }
139 mbox->ndevs = ndevs;
140 for (devid = 0; devid < ndevs; devid++) {
141 mdev = &mbox->dev[devid];
142 mdev->mbase = (void *)(mbox->hwbase + (devid * MBOX_SIZE));
143 rte_spinlock_init(&mdev->mbox_lock);
144
145 otx2_mbox_reset(mbox, devid);
146 }
147
148 return 0;
149}
150
151
152
153
154
155struct mbox_msghdr *
156otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid, int size,
157 int size_rsp)
158{
159 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
160 struct mbox_msghdr *msghdr = NULL;
161
162 rte_spinlock_lock(&mdev->mbox_lock);
163 size = RTE_ALIGN(size, MBOX_MSG_ALIGN);
164 size_rsp = RTE_ALIGN(size_rsp, MBOX_MSG_ALIGN);
165
166 if ((mdev->msg_size + size) > mbox->tx_size - msgs_offset())
167 goto exit;
168 if ((mdev->rsp_size + size_rsp) > mbox->rx_size - msgs_offset())
169 goto exit;
170 if (mdev->msg_size == 0)
171 mdev->num_msgs = 0;
172 mdev->num_msgs++;
173
174 msghdr = (struct mbox_msghdr *)(((uintptr_t)mdev->mbase +
175 mbox->tx_start + msgs_offset() + mdev->msg_size));
176
177
178 otx2_mbox_memset(msghdr, 0, sizeof(*msghdr) + size);
179
180 msghdr->ver = OTX2_MBOX_VERSION;
181 mdev->msg_size += size;
182 mdev->rsp_size += size_rsp;
183 msghdr->next_msgoff = mdev->msg_size + msgs_offset();
184exit:
185 rte_spinlock_unlock(&mdev->mbox_lock);
186
187 return msghdr;
188}
189
190
191
192
193
194void
195otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
196{
197 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
198 struct mbox_hdr *tx_hdr =
199 (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->tx_start);
200 struct mbox_hdr *rx_hdr =
201 (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
202
203
204 tx_hdr->msg_size = mdev->msg_size;
205 mdev->msg_size = 0;
206 mdev->rsp_size = 0;
207 mdev->msgs_acked = 0;
208
209
210
211
212 tx_hdr->num_msgs = mdev->num_msgs;
213 rx_hdr->num_msgs = 0;
214
215
216 rte_wmb();
217
218
219
220
221 rte_write64(1, (volatile void *)(mbox->reg_base +
222 (mbox->trigger | (devid << mbox->tr_shift))));
223}
224
225
226
227
228
229int
230otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid, void **msg)
231{
232 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
233 struct mbox_msghdr *msghdr;
234 uint64_t offset;
235 int rc;
236
237 rc = otx2_mbox_wait_for_rsp(mbox, devid);
238 if (rc != 1)
239 return -EIO;
240
241 rte_rmb();
242
243 offset = mbox->rx_start +
244 RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
245 msghdr = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
246 if (msg != NULL)
247 *msg = msghdr;
248
249 return msghdr->rc;
250}
251
252
253
254
255static int
256mbox_poll(struct otx2_mbox *mbox, uint32_t wait)
257{
258 uint32_t timeout = 0, sleep = 1;
259 uint32_t wait_us = wait * 1000;
260 uint64_t rsp_reg = 0;
261 uintptr_t reg_addr;
262
263 reg_addr = mbox->reg_base + mbox->intr_offset;
264 do {
265 rsp_reg = otx2_read64(reg_addr);
266
267 if (timeout >= wait_us)
268 return -ETIMEDOUT;
269
270 rte_delay_us(sleep);
271 timeout += sleep;
272 } while (!rsp_reg);
273
274 rte_smp_rmb();
275
276
277 otx2_write64(rsp_reg, reg_addr);
278
279
280 otx2_mbox_reset(mbox, 0);
281
282 return 0;
283}
284
285
286
287
288
289int
290otx2_mbox_get_rsp_tmo(struct otx2_mbox *mbox, int devid, void **msg,
291 uint32_t tmo)
292{
293 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
294 struct mbox_msghdr *msghdr;
295 uint64_t offset;
296 int rc;
297
298 rc = otx2_mbox_wait_for_rsp_tmo(mbox, devid, tmo);
299 if (rc != 1)
300 return -EIO;
301
302 rte_rmb();
303
304 offset = mbox->rx_start +
305 RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
306 msghdr = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
307 if (msg != NULL)
308 *msg = msghdr;
309
310 return msghdr->rc;
311}
312
313static int
314mbox_wait(struct otx2_mbox *mbox, int devid, uint32_t rst_timo)
315{
316 volatile struct otx2_mbox_dev *mdev = &mbox->dev[devid];
317 uint32_t timeout = 0, sleep = 1;
318
319 rst_timo = rst_timo * 1000;
320 while (mdev->num_msgs > mdev->msgs_acked) {
321 rte_delay_us(sleep);
322 timeout += sleep;
323 if (timeout >= rst_timo) {
324 struct mbox_hdr *tx_hdr =
325 (struct mbox_hdr *)((uintptr_t)mdev->mbase +
326 mbox->tx_start);
327 struct mbox_hdr *rx_hdr =
328 (struct mbox_hdr *)((uintptr_t)mdev->mbase +
329 mbox->rx_start);
330
331 otx2_err("MBOX[devid: %d] message wait timeout %d, "
332 "num_msgs: %d, msgs_acked: %d "
333 "(tx/rx num_msgs: %d/%d), msg_size: %d, "
334 "rsp_size: %d",
335 devid, timeout, mdev->num_msgs,
336 mdev->msgs_acked, tx_hdr->num_msgs,
337 rx_hdr->num_msgs, mdev->msg_size,
338 mdev->rsp_size);
339
340 return -EIO;
341 }
342 rte_rmb();
343 }
344 return 0;
345}
346
347int
348otx2_mbox_wait_for_rsp_tmo(struct otx2_mbox *mbox, int devid, uint32_t tmo)
349{
350 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
351 int rc = 0;
352
353
354 rte_rmb();
355
356 if (mbox->trigger == RVU_PF_VFX_PFVF_MBOX1 ||
357 mbox->trigger == RVU_PF_VFX_PFVF_MBOX0) {
358
359 tmo = tmo * 2;
360 }
361
362
363 if (rte_thread_is_intr())
364 rc = mbox_poll(mbox, tmo);
365 else
366 rc = mbox_wait(mbox, devid, tmo);
367
368 if (!rc)
369 rc = mdev->num_msgs;
370
371 return rc;
372}
373
374
375
376
377
378int
379otx2_mbox_wait_for_rsp(struct otx2_mbox *mbox, int devid)
380{
381 return otx2_mbox_wait_for_rsp_tmo(mbox, devid, MBOX_RSP_TIMEOUT);
382}
383
384int
385otx2_mbox_get_availmem(struct otx2_mbox *mbox, int devid)
386{
387 struct otx2_mbox_dev *mdev = &mbox->dev[devid];
388 int avail;
389
390 rte_spinlock_lock(&mdev->mbox_lock);
391 avail = mbox->tx_size - mdev->msg_size - msgs_offset();
392 rte_spinlock_unlock(&mdev->mbox_lock);
393
394 return avail;
395}
396
397int
398otx2_send_ready_msg(struct otx2_mbox *mbox, uint16_t *pcifunc)
399{
400 struct ready_msg_rsp *rsp;
401 int rc;
402
403 otx2_mbox_alloc_msg_ready(mbox);
404
405 otx2_mbox_msg_send(mbox, 0);
406 rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
407 if (rc)
408 return rc;
409
410 if (rsp->hdr.ver != OTX2_MBOX_VERSION) {
411 otx2_err("Incompatible MBox versions(AF: 0x%04x DPDK: 0x%04x)",
412 rsp->hdr.ver, OTX2_MBOX_VERSION);
413 return -EPIPE;
414 }
415
416 if (pcifunc)
417 *pcifunc = rsp->hdr.pcifunc;
418
419 return 0;
420}
421
422int
423otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid, uint16_t pcifunc,
424 uint16_t id)
425{
426 struct msg_rsp *rsp;
427
428 rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(mbox, devid, sizeof(*rsp));
429 if (!rsp)
430 return -ENOMEM;
431 rsp->hdr.id = id;
432 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
433 rsp->hdr.rc = MBOX_MSG_INVALID;
434 rsp->hdr.pcifunc = pcifunc;
435
436 return 0;
437}
438
439
440
441
442
443const char *otx2_mbox_id2name(uint16_t id)
444{
445 switch (id) {
446#define M(_name, _id, _1, _2, _3) case _id: return # _name;
447 MBOX_MESSAGES
448 MBOX_UP_CGX_MESSAGES
449#undef M
450 default :
451 return "INVALID ID";
452 }
453}
454
455int otx2_mbox_id2size(uint16_t id)
456{
457 switch (id) {
458#define M(_1, _id, _2, _req_type, _3) case _id: return sizeof(struct _req_type);
459 MBOX_MESSAGES
460 MBOX_UP_CGX_MESSAGES
461#undef M
462 default :
463 return 0;
464 }
465}
466