common/octeontx2: fix crash on running procinfo
[dpdk.git] / drivers / common / octeontx2 / otx2_mbox.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
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
29 static inline uint16_t
30 msgs_offset(void)
31 {
32         return RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
33 }
34
35 void
36 otx2_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
44 void
45 otx2_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
63 int
64 otx2_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                 /* Init header to reset value */
145                 otx2_mbox_reset(mbox, devid);
146         }
147
148         return 0;
149 }
150
151 /**
152  * @internal
153  * Allocate a message response
154  */
155 struct mbox_msghdr *
156 otx2_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         /* Check if there is space in mailbox */
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         /* Clear the whole msg region */
178         otx2_mbox_memset(msghdr, 0, sizeof(*msghdr) + size);
179         /* Init message header with reset values */
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();
184 exit:
185         rte_spinlock_unlock(&mdev->mbox_lock);
186
187         return msghdr;
188 }
189
190 /**
191  * @internal
192  * Send a mailbox message
193  */
194 void
195 otx2_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         /* Reset header for next messages */
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         /* num_msgs != 0 signals to the peer that the buffer has a number of
210          * messages. So this should be written after copying txmem
211          */
212         tx_hdr->num_msgs = mdev->num_msgs;
213         rx_hdr->num_msgs = 0;
214
215         /* Sync mbox data into memory */
216         rte_wmb();
217
218         /* The interrupt should be fired after num_msgs is written
219          * to the shared memory
220          */
221         rte_write64(1, (volatile void *)(mbox->reg_base +
222                 (mbox->trigger | (devid << mbox->tr_shift))));
223 }
224
225 /**
226  * @internal
227  * Wait and get mailbox response
228  */
229 int
230 otx2_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  * Polling for given wait time to get mailbox response
254  */
255 static int
256 mbox_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         /* Clear interrupt */
277         otx2_write64(rsp_reg, reg_addr);
278
279         /* Reset mbox */
280         otx2_mbox_reset(mbox, 0);
281
282         return 0;
283 }
284
285 /**
286  * @internal
287  * Wait and get mailbox response with timeout
288  */
289 int
290 otx2_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
313 static int
314 mbox_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; /* Milli seconds to micro seconds */
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
347 int
348 otx2_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         /* Sync with mbox region */
354         rte_rmb();
355
356         if (mbox->trigger == RVU_PF_VFX_PFVF_MBOX1 ||
357                 mbox->trigger == RVU_PF_VFX_PFVF_MBOX0) {
358                 /* In case of VF, Wait a bit more to account round trip delay */
359                 tmo = tmo * 2;
360         }
361
362         /* Wait message */
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  * @internal
376  * Wait for the mailbox response
377  */
378 int
379 otx2_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
384 int
385 otx2_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
397 int
398 otx2_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
422 int
423 otx2_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  * @internal
441  * Convert mail box ID to name
442  */
443 const 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
455 int 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 }