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