New upstream version 17.11.1
[deb_dpdk.git] / drivers / mempool / octeontx / octeontx_mbox.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright (C) Cavium, Inc. 2017.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
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
15  *       distribution.
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.
19  *
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.
31  */
32
33 #include <string.h>
34
35 #include <rte_atomic.h>
36 #include <rte_common.h>
37 #include <rte_cycles.h>
38 #include <rte_io.h>
39 #include <rte_spinlock.h>
40
41 #include "octeontx_mbox.h"
42 #include "octeontx_pool_logs.h"
43
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 */)
47
48 /* Mbox channel state */
49 enum {
50         MBOX_CHAN_STATE_REQ = 1,
51         MBOX_CHAN_STATE_RES = 0,
52 };
53
54 /* Response messages */
55 enum {
56         MBOX_RET_SUCCESS,
57         MBOX_RET_INVALID,
58         MBOX_RET_INTERNAL_ERR,
59 };
60
61 struct mbox {
62         int init_once;
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 */
66         rte_spinlock_t lock;
67 };
68
69 static struct mbox octeontx_mbox;
70
71 /*
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
75  */
76 struct mbox_ram_hdr {
77         union {
78                 uint64_t u64;
79                 struct {
80                         uint8_t chan_state : 1;
81                         uint8_t coproc : 7;
82                         uint8_t msg;
83                         uint8_t vfid;
84                         uint8_t res_code;
85                         uint16_t tag;
86                         uint16_t len;
87                 };
88         };
89 };
90
91 static inline void
92 mbox_msgcpy(volatile uint8_t *d, volatile const uint8_t *s, uint16_t size)
93 {
94         uint16_t i;
95
96         for (i = 0; i < size; i++)
97                 d[i] = s[i];
98 }
99
100 static inline void
101 mbox_send_request(struct mbox *m, struct octeontx_mbox_hdr *hdr,
102                         const void *txmsg, uint16_t txsize)
103 {
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);
108
109         /*
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
113          */
114         old_hdr.u64 = rte_read64(ram_mbox_hdr);
115         m->tag_own = (old_hdr.tag + 2) & (~0x1ul); /* next even number */
116
117         /* Copy msg body */
118         if (txmsg)
119                 mbox_msgcpy(ram_mbox_msg, txmsg, txsize);
120
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;
128
129         /* Write the msg header */
130         rte_write64(new_hdr.u64, ram_mbox_hdr);
131         rte_smp_wmb();
132         /* Notify PF about the new msg - write to MBOX reg generates PF IRQ */
133         rte_write64(0, m->reg);
134 }
135
136 static inline int
137 mbox_wait_response(struct mbox *m, struct octeontx_mbox_hdr *hdr,
138                         void *rxmsg, uint16_t rxsize)
139 {
140         int res = 0, wait;
141         uint16_t len;
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);
145
146         /* Wait for response */
147         wait = MBOX_WAIT_TIME_SEC * 1000 * 10;
148         while (wait > 0) {
149                 rte_delay_us(100);
150                 rx_hdr.u64 = rte_read64(ram_mbox_hdr);
151                 if (rx_hdr.chan_state == MBOX_CHAN_STATE_RES)
152                         break;
153                 --wait;
154         }
155
156         hdr->res_code = rx_hdr.res_code;
157         m->tag_own++;
158
159         /* Timeout */
160         if (wait <= 0) {
161                 res = -ETIMEDOUT;
162                 goto error;
163         }
164
165         /* Tag mismatch */
166         if (m->tag_own != rx_hdr.tag) {
167                 res = -EINVAL;
168                 goto error;
169         }
170
171         /* PF nacked the msg */
172         if (rx_hdr.res_code != MBOX_RET_SUCCESS) {
173                 res = -EBADMSG;
174                 goto error;
175         }
176
177         len = RTE_MIN(rx_hdr.len, rxsize);
178         if (rxmsg)
179                 mbox_msgcpy(rxmsg, ram_mbox_msg, len);
180
181         return len;
182
183 error:
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,
186                         hdr->res_code);
187         return res;
188 }
189
190 static inline int
191 mbox_send(struct mbox *m, struct octeontx_mbox_hdr *hdr, const void *txmsg,
192                 uint16_t txsize, void *rxmsg, uint16_t rxsize)
193 {
194         int res = -EINVAL;
195
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);
200                 return res;
201         }
202
203         rte_spinlock_lock(&m->lock);
204
205         mbox_send_request(m, hdr, txmsg, txsize);
206         res = mbox_wait_response(m, hdr, rxmsg, rxsize);
207
208         rte_spinlock_unlock(&m->lock);
209         return res;
210 }
211
212 static inline int
213 mbox_setup(struct mbox *m)
214 {
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);
220
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);
224                         return -EINVAL;
225                 }
226                 m->init_once = 1;
227         }
228         return 0;
229 }
230
231 int
232 octeontx_ssovf_mbox_send(struct octeontx_mbox_hdr *hdr, void *txdata,
233                                  uint16_t txlen, void *rxdata, uint16_t rxlen)
234 {
235         struct mbox *m = &octeontx_mbox;
236
237         RTE_BUILD_BUG_ON(sizeof(struct mbox_ram_hdr) != 8);
238         if (rte_eal_process_type() != RTE_PROC_PRIMARY || mbox_setup(m))
239                 return -EINVAL;
240
241         return mbox_send(m, hdr, txdata, txlen, rxdata, rxlen);
242 }