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
msgs_offset(void)30 msgs_offset(void)
31 {
32 	return RTE_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
33 }
34 
35 void
otx2_mbox_fini(struct otx2_mbox * mbox)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
otx2_mbox_reset(struct otx2_mbox * mbox,int devid)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
otx2_mbox_init(struct otx2_mbox * mbox,uintptr_t hwbase,uintptr_t reg_base,int direction,int ndevs,uint64_t intr_offset)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 *
otx2_mbox_alloc_msg_rsp(struct otx2_mbox * mbox,int devid,int size,int size_rsp)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
otx2_mbox_msg_send(struct otx2_mbox * mbox,int devid)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
otx2_mbox_get_rsp(struct otx2_mbox * mbox,int devid,void ** msg)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
mbox_poll(struct otx2_mbox * mbox,uint32_t wait)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
otx2_mbox_get_rsp_tmo(struct otx2_mbox * mbox,int devid,void ** msg,uint32_t tmo)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
mbox_wait(struct otx2_mbox * mbox,int devid,uint32_t rst_timo)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
otx2_mbox_wait_for_rsp_tmo(struct otx2_mbox * mbox,int devid,uint32_t tmo)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
otx2_mbox_wait_for_rsp(struct otx2_mbox * mbox,int devid)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
otx2_mbox_get_availmem(struct otx2_mbox * mbox,int devid)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
otx2_send_ready_msg(struct otx2_mbox * mbox,uint16_t * pcifunc)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
otx2_reply_invalid_msg(struct otx2_mbox * mbox,int devid,uint16_t pcifunc,uint16_t id)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  */
otx2_mbox_id2name(uint16_t id)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 
otx2_mbox_id2size(uint16_t id)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 }
466