4 * Copyright (C) Cavium, Inc. 2017.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of Cavium, Inc nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <rte_atomic.h>
36 #include <rte_common.h>
37 #include <rte_cycles.h>
39 #include <rte_spinlock.h>
41 #include "octeontx_mbox.h"
42 #include "octeontx_pool_logs.h"
44 /* Mbox operation timeout in seconds */
45 #define MBOX_WAIT_TIME_SEC 3
46 #define MAX_RAM_MBOX_LEN ((SSOW_BAR4_LEN >> 1) - 8 /* Mbox header */)
48 /* Mbox channel state */
50 MBOX_CHAN_STATE_REQ = 1,
51 MBOX_CHAN_STATE_RES = 0,
54 /* Response messages */
58 MBOX_RET_INTERNAL_ERR,
63 uint8_t *ram_mbox_base; /* Base address of mbox message stored in ram */
64 uint8_t *reg; /* Store to this register triggers PF mbox interrupt */
65 uint16_t tag_own; /* Last tag which was written to own channel */
69 static struct mbox octeontx_mbox;
72 * Structure used for mbox synchronization
73 * This structure sits at the begin of Mbox RAM and used as main
74 * synchronization point for channel communication
80 uint8_t chan_state : 1;
92 mbox_msgcpy(uint8_t *d, const uint8_t *s, uint16_t size)
96 for (i = 0; i < size; i++)
101 mbox_send_request(struct mbox *m, struct octeontx_mbox_hdr *hdr,
102 const void *txmsg, uint16_t txsize)
104 struct mbox_ram_hdr old_hdr;
105 struct mbox_ram_hdr new_hdr = { {0} };
106 uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
107 uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
110 * Initialize the channel with the tag left by last send.
111 * On success full mbox send complete, PF increments the tag by one.
112 * The sender can validate integrity of PF message with this scheme
114 old_hdr.u64 = rte_read64(ram_mbox_hdr);
115 m->tag_own = (old_hdr.tag + 2) & (~0x1ul); /* next even number */
119 mbox_msgcpy(ram_mbox_msg, txmsg, txsize);
121 /* Prepare new hdr */
122 new_hdr.chan_state = MBOX_CHAN_STATE_REQ;
123 new_hdr.coproc = hdr->coproc;
124 new_hdr.msg = hdr->msg;
125 new_hdr.vfid = hdr->vfid;
126 new_hdr.tag = m->tag_own;
127 new_hdr.len = txsize;
129 /* Write the msg header */
130 rte_write64(new_hdr.u64, ram_mbox_hdr);
132 /* Notify PF about the new msg - write to MBOX reg generates PF IRQ */
133 rte_write64(0, m->reg);
137 mbox_wait_response(struct mbox *m, struct octeontx_mbox_hdr *hdr,
138 void *rxmsg, uint16_t rxsize)
142 struct mbox_ram_hdr rx_hdr;
143 uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
144 uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
146 /* Wait for response */
147 wait = MBOX_WAIT_TIME_SEC * 1000 * 10;
150 rx_hdr.u64 = rte_read64(ram_mbox_hdr);
151 if (rx_hdr.chan_state == MBOX_CHAN_STATE_RES)
156 hdr->res_code = rx_hdr.res_code;
166 if (m->tag_own != rx_hdr.tag) {
171 /* PF nacked the msg */
172 if (rx_hdr.res_code != MBOX_RET_SUCCESS) {
177 len = RTE_MIN(rx_hdr.len, rxsize);
179 mbox_msgcpy(rxmsg, ram_mbox_msg, len);
184 mbox_log_err("Failed to send mbox(%d/%d) coproc=%d msg=%d ret=(%d,%d)",
185 m->tag_own, rx_hdr.tag, hdr->coproc, hdr->msg, res,
191 mbox_send(struct mbox *m, struct octeontx_mbox_hdr *hdr, const void *txmsg,
192 uint16_t txsize, void *rxmsg, uint16_t rxsize)
196 if (m->init_once == 0 || hdr == NULL ||
197 txsize > MAX_RAM_MBOX_LEN || rxsize > MAX_RAM_MBOX_LEN) {
198 mbox_log_err("Invalid init_once=%d hdr=%p txsz=%d rxsz=%d",
199 m->init_once, hdr, txsize, rxsize);
203 rte_spinlock_lock(&m->lock);
205 mbox_send_request(m, hdr, txmsg, txsize);
206 res = mbox_wait_response(m, hdr, rxmsg, rxsize);
208 rte_spinlock_unlock(&m->lock);
213 mbox_setup(struct mbox *m)
215 if (unlikely(m->init_once == 0)) {
216 rte_spinlock_init(&m->lock);
217 m->ram_mbox_base = octeontx_ssovf_bar(OCTEONTX_SSO_HWS, 0, 4);
218 m->reg = octeontx_ssovf_bar(OCTEONTX_SSO_GROUP, 0, 0);
219 m->reg += SSO_VHGRP_PF_MBOX(1);
221 if (m->ram_mbox_base == NULL || m->reg == NULL) {
222 mbox_log_err("Invalid ram_mbox_base=%p or reg=%p",
223 m->ram_mbox_base, m->reg);
232 octeontx_ssovf_mbox_send(struct octeontx_mbox_hdr *hdr, void *txdata,
233 uint16_t txlen, void *rxdata, uint16_t rxlen)
235 struct mbox *m = &octeontx_mbox;
237 RTE_BUILD_BUG_ON(sizeof(struct mbox_ram_hdr) != 8);
238 if (rte_eal_process_type() != RTE_PROC_PRIMARY || mbox_setup(m))
241 return mbox_send(m, hdr, txdata, txlen, rxdata, rxlen);