1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Cavium, Inc
7 #include <rte_atomic.h>
8 #include <rte_common.h>
9 #include <rte_cycles.h>
11 #include <rte_spinlock.h>
13 #include "octeontx_mbox.h"
15 /* Mbox operation timeout in seconds */
16 #define MBOX_WAIT_TIME_SEC 3
17 #define MAX_RAM_MBOX_LEN ((SSOW_BAR4_LEN >> 1) - 8 /* Mbox header */)
19 /* Mbox channel state */
21 MBOX_CHAN_STATE_REQ = 1,
22 MBOX_CHAN_STATE_RES = 0,
25 /* Response messages */
29 MBOX_RET_INTERNAL_ERR,
35 uint8_t *ram_mbox_base; /* Base address of mbox message stored in ram */
36 uint8_t *reg; /* Store to this register triggers PF mbox interrupt */
37 uint16_t tag_own; /* Last tag which was written to own channel */
38 uint16_t domain; /* Domain */
42 static struct mbox octeontx_mbox;
45 * Structure used for mbox synchronization
46 * This structure sits at the begin of Mbox RAM and used as main
47 * synchronization point for channel communication
53 uint8_t chan_state : 1;
64 /* MBOX interface version message */
65 struct mbox_intf_ver {
71 int octeontx_logtype_mbox;
73 RTE_INIT(otx_init_log)
75 octeontx_logtype_mbox = rte_log_register("pmd.octeontx.mbox");
76 if (octeontx_logtype_mbox >= 0)
77 rte_log_set_level(octeontx_logtype_mbox, RTE_LOG_NOTICE);
81 mbox_msgcpy(volatile uint8_t *d, volatile const uint8_t *s, uint16_t size)
85 for (i = 0; i < size; i++)
90 mbox_send_request(struct mbox *m, struct octeontx_mbox_hdr *hdr,
91 const void *txmsg, uint16_t txsize)
93 struct mbox_ram_hdr old_hdr;
94 struct mbox_ram_hdr new_hdr = { {0} };
95 uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
96 uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
99 * Initialize the channel with the tag left by last send.
100 * On success full mbox send complete, PF increments the tag by one.
101 * The sender can validate integrity of PF message with this scheme
103 old_hdr.u64 = rte_read64(ram_mbox_hdr);
104 m->tag_own = (old_hdr.tag + 2) & (~0x1ul); /* next even number */
108 mbox_msgcpy(ram_mbox_msg, txmsg, txsize);
110 /* Prepare new hdr */
111 new_hdr.chan_state = MBOX_CHAN_STATE_REQ;
112 new_hdr.coproc = hdr->coproc;
113 new_hdr.msg = hdr->msg;
114 new_hdr.vfid = hdr->vfid;
115 new_hdr.tag = m->tag_own;
116 new_hdr.len = txsize;
118 /* Write the msg header */
119 rte_write64(new_hdr.u64, ram_mbox_hdr);
121 /* Notify PF about the new msg - write to MBOX reg generates PF IRQ */
122 rte_write64(0, m->reg);
126 mbox_wait_response(struct mbox *m, struct octeontx_mbox_hdr *hdr,
127 void *rxmsg, uint16_t rxsize)
131 struct mbox_ram_hdr rx_hdr;
132 uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
133 uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
135 /* Wait for response */
136 wait = MBOX_WAIT_TIME_SEC * 1000 * 10;
139 rx_hdr.u64 = rte_read64(ram_mbox_hdr);
140 if (rx_hdr.chan_state == MBOX_CHAN_STATE_RES)
145 hdr->res_code = rx_hdr.res_code;
155 if (m->tag_own != rx_hdr.tag) {
160 /* PF nacked the msg */
161 if (rx_hdr.res_code != MBOX_RET_SUCCESS) {
166 len = RTE_MIN(rx_hdr.len, rxsize);
168 mbox_msgcpy(rxmsg, ram_mbox_msg, len);
173 mbox_log_err("Failed to send mbox(%d/%d) coproc=%d msg=%d ret=(%d,%d)",
174 m->tag_own, rx_hdr.tag, hdr->coproc, hdr->msg, res,
180 mbox_send(struct mbox *m, struct octeontx_mbox_hdr *hdr, const void *txmsg,
181 uint16_t txsize, void *rxmsg, uint16_t rxsize)
185 if (m->init_once == 0 || hdr == NULL ||
186 txsize > MAX_RAM_MBOX_LEN || rxsize > MAX_RAM_MBOX_LEN) {
187 mbox_log_err("Invalid init_once=%d hdr=%p txsz=%d rxsz=%d",
188 m->init_once, hdr, txsize, rxsize);
192 rte_spinlock_lock(&m->lock);
194 mbox_send_request(m, hdr, txmsg, txsize);
195 res = mbox_wait_response(m, hdr, rxmsg, rxsize);
197 rte_spinlock_unlock(&m->lock);
202 octeontx_mbox_set_ram_mbox_base(uint8_t *ram_mbox_base, uint16_t domain)
204 struct mbox *m = &octeontx_mbox;
209 if (ram_mbox_base == NULL) {
210 mbox_log_err("Invalid ram_mbox_base=%p", ram_mbox_base);
214 m->ram_mbox_base = ram_mbox_base;
216 if (m->reg != NULL) {
217 rte_spinlock_init(&m->lock);
226 octeontx_mbox_set_reg(uint8_t *reg, uint16_t domain)
228 struct mbox *m = &octeontx_mbox;
234 mbox_log_err("Invalid reg=%p", reg);
240 if (m->ram_mbox_base != NULL) {
241 rte_spinlock_init(&m->lock);
250 octeontx_mbox_send(struct octeontx_mbox_hdr *hdr, void *txdata,
251 uint16_t txlen, void *rxdata, uint16_t rxlen)
253 struct mbox *m = &octeontx_mbox;
255 RTE_BUILD_BUG_ON(sizeof(struct mbox_ram_hdr) != 8);
256 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
259 return mbox_send(m, hdr, txdata, txlen, rxdata, rxlen);
263 octeontx_start_domain(void)
265 struct octeontx_mbox_hdr hdr = {0};
266 int result = -EINVAL;
268 hdr.coproc = NO_COPROC;
269 hdr.msg = RM_START_APP;
271 result = octeontx_mbox_send(&hdr, NULL, 0, NULL, 0);
273 mbox_log_err("Could not start domain. Err=%d. FuncErr=%d\n",
274 result, hdr.res_code);
282 octeontx_check_mbox_version(struct mbox_intf_ver *app_intf_ver,
283 struct mbox_intf_ver *intf_ver)
285 struct mbox_intf_ver kernel_intf_ver = {0};
286 struct octeontx_mbox_hdr hdr = {0};
290 hdr.coproc = NO_COPROC;
291 hdr.msg = RM_INTERFACE_VERSION;
293 result = octeontx_mbox_send(&hdr, app_intf_ver,
294 sizeof(struct mbox_intf_ver),
295 &kernel_intf_ver, sizeof(kernel_intf_ver));
296 if (result != sizeof(kernel_intf_ver)) {
297 mbox_log_err("Could not send interface version. Err=%d. FuncErr=%d\n",
298 result, hdr.res_code);
303 *intf_ver = kernel_intf_ver;
305 if (app_intf_ver->platform != kernel_intf_ver.platform ||
306 app_intf_ver->major != kernel_intf_ver.major ||
307 app_intf_ver->minor != kernel_intf_ver.minor)
314 octeontx_mbox_init(void)
316 struct mbox_intf_ver MBOX_INTERFACE_VERSION = {
321 struct mbox_intf_ver rm_intf_ver = {0};
322 struct mbox *m = &octeontx_mbox;
328 ret = octeontx_start_domain();
334 ret = octeontx_check_mbox_version(&MBOX_INTERFACE_VERSION,
337 mbox_log_err("MBOX version: Kernel(%d.%d.%d) != DPDK(%d.%d.%d)",
338 rm_intf_ver.platform, rm_intf_ver.major,
339 rm_intf_ver.minor, MBOX_INTERFACE_VERSION.platform,
340 MBOX_INTERFACE_VERSION.major,
341 MBOX_INTERFACE_VERSION.minor);
353 octeontx_get_global_domain(void)
355 struct mbox *m = &octeontx_mbox;