b4abc6235a51e637b9a21d672b474af53518b0fd
[deb_dpdk.git] / drivers / net / liquidio / base / lio_mbox.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Cavium, Inc. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_ethdev.h>
35 #include <rte_cycles.h>
36
37 #include "lio_logs.h"
38 #include "lio_struct.h"
39 #include "lio_mbox.h"
40
41 /**
42  * lio_mbox_read:
43  * @mbox: Pointer mailbox
44  *
45  * Reads the 8-bytes of data from the mbox register
46  * Writes back the acknowledgment indicating completion of read
47  */
48 int
49 lio_mbox_read(struct lio_mbox *mbox)
50 {
51         union lio_mbox_message msg;
52         int ret = 0;
53
54         msg.mbox_msg64 = rte_read64(mbox->mbox_read_reg);
55
56         if ((msg.mbox_msg64 == LIO_PFVFACK) || (msg.mbox_msg64 == LIO_PFVFSIG))
57                 return 0;
58
59         if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) {
60                 mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] =
61                                         msg.mbox_msg64;
62                 mbox->mbox_req.recv_len++;
63         } else {
64                 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) {
65                         mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
66                                         msg.mbox_msg64;
67                         mbox->mbox_resp.recv_len++;
68                 } else {
69                         if ((mbox->state & LIO_MBOX_STATE_IDLE) &&
70                                         (msg.s.type == LIO_MBOX_REQUEST)) {
71                                 mbox->state &= ~LIO_MBOX_STATE_IDLE;
72                                 mbox->state |= LIO_MBOX_STATE_REQ_RECEIVING;
73                                 mbox->mbox_req.msg.mbox_msg64 = msg.mbox_msg64;
74                                 mbox->mbox_req.q_no = mbox->q_no;
75                                 mbox->mbox_req.recv_len = 1;
76                         } else {
77                                 if ((mbox->state &
78                                      LIO_MBOX_STATE_RES_PENDING) &&
79                                     (msg.s.type == LIO_MBOX_RESPONSE)) {
80                                         mbox->state &=
81                                                 ~LIO_MBOX_STATE_RES_PENDING;
82                                         mbox->state |=
83                                                 LIO_MBOX_STATE_RES_RECEIVING;
84                                         mbox->mbox_resp.msg.mbox_msg64 =
85                                                                 msg.mbox_msg64;
86                                         mbox->mbox_resp.q_no = mbox->q_no;
87                                         mbox->mbox_resp.recv_len = 1;
88                                 } else {
89                                         rte_write64(LIO_PFVFERR,
90                                                     mbox->mbox_read_reg);
91                                         mbox->state |= LIO_MBOX_STATE_ERROR;
92                                         return -1;
93                                 }
94                         }
95                 }
96         }
97
98         if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) {
99                 if (mbox->mbox_req.recv_len < msg.s.len) {
100                         ret = 0;
101                 } else {
102                         mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVING;
103                         mbox->state |= LIO_MBOX_STATE_REQ_RECEIVED;
104                         ret = 1;
105                 }
106         } else {
107                 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) {
108                         if (mbox->mbox_resp.recv_len < msg.s.len) {
109                                 ret = 0;
110                         } else {
111                                 mbox->state &= ~LIO_MBOX_STATE_RES_RECEIVING;
112                                 mbox->state |= LIO_MBOX_STATE_RES_RECEIVED;
113                                 ret = 1;
114                         }
115                 } else {
116                         RTE_ASSERT(0);
117                 }
118         }
119
120         rte_write64(LIO_PFVFACK, mbox->mbox_read_reg);
121
122         return ret;
123 }
124
125 /**
126  * lio_mbox_write:
127  * @lio_dev: Pointer lio device
128  * @mbox_cmd: Cmd to send to mailbox.
129  *
130  * Populates the queue specific mbox structure
131  * with cmd information.
132  * Write the cmd to mbox register
133  */
134 int
135 lio_mbox_write(struct lio_device *lio_dev,
136                struct lio_mbox_cmd *mbox_cmd)
137 {
138         struct lio_mbox *mbox = lio_dev->mbox[mbox_cmd->q_no];
139         uint32_t count, i, ret = LIO_MBOX_STATUS_SUCCESS;
140
141         if ((mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) &&
142                         !(mbox->state & LIO_MBOX_STATE_REQ_RECEIVED))
143                 return LIO_MBOX_STATUS_FAILED;
144
145         if ((mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) &&
146                         !(mbox->state & LIO_MBOX_STATE_IDLE))
147                 return LIO_MBOX_STATUS_BUSY;
148
149         if (mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) {
150                 rte_memcpy(&mbox->mbox_resp, mbox_cmd,
151                            sizeof(struct lio_mbox_cmd));
152                 mbox->state = LIO_MBOX_STATE_RES_PENDING;
153         }
154
155         count = 0;
156
157         while (rte_read64(mbox->mbox_write_reg) != LIO_PFVFSIG) {
158                 rte_delay_ms(1);
159                 if (count++ == 1000) {
160                         ret = LIO_MBOX_STATUS_FAILED;
161                         break;
162                 }
163         }
164
165         if (ret == LIO_MBOX_STATUS_SUCCESS) {
166                 rte_write64(mbox_cmd->msg.mbox_msg64, mbox->mbox_write_reg);
167                 for (i = 0; i < (uint32_t)(mbox_cmd->msg.s.len - 1); i++) {
168                         count = 0;
169                         while (rte_read64(mbox->mbox_write_reg) !=
170                                         LIO_PFVFACK) {
171                                 rte_delay_ms(1);
172                                 if (count++ == 1000) {
173                                         ret = LIO_MBOX_STATUS_FAILED;
174                                         break;
175                                 }
176                         }
177                         rte_write64(mbox_cmd->data[i], mbox->mbox_write_reg);
178                 }
179         }
180
181         if (mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) {
182                 mbox->state = LIO_MBOX_STATE_IDLE;
183                 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
184         } else {
185                 if ((!mbox_cmd->msg.s.resp_needed) ||
186                                 (ret == LIO_MBOX_STATUS_FAILED)) {
187                         mbox->state &= ~LIO_MBOX_STATE_RES_PENDING;
188                         if (!(mbox->state & (LIO_MBOX_STATE_REQ_RECEIVING |
189                                              LIO_MBOX_STATE_REQ_RECEIVED)))
190                                 mbox->state = LIO_MBOX_STATE_IDLE;
191                 }
192         }
193
194         return ret;
195 }
196
197 /**
198  * lio_mbox_process_cmd:
199  * @mbox: Pointer mailbox
200  * @mbox_cmd: Pointer to command received
201  *
202  * Process the cmd received in mbox
203  */
204 static int
205 lio_mbox_process_cmd(struct lio_mbox *mbox,
206                      struct lio_mbox_cmd *mbox_cmd)
207 {
208         struct lio_device *lio_dev = mbox->lio_dev;
209
210         if (mbox_cmd->msg.s.cmd == LIO_CORES_CRASHED)
211                 lio_dev_err(lio_dev, "Octeon core(s) crashed or got stuck!\n");
212
213         return 0;
214 }
215
216 /**
217  * Process the received mbox message.
218  */
219 int
220 lio_mbox_process_message(struct lio_mbox *mbox)
221 {
222         struct lio_mbox_cmd mbox_cmd;
223
224         if (mbox->state & LIO_MBOX_STATE_ERROR) {
225                 if (mbox->state & (LIO_MBOX_STATE_RES_PENDING |
226                                    LIO_MBOX_STATE_RES_RECEIVING)) {
227                         rte_memcpy(&mbox_cmd, &mbox->mbox_resp,
228                                    sizeof(struct lio_mbox_cmd));
229                         mbox->state = LIO_MBOX_STATE_IDLE;
230                         rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
231                         mbox_cmd.recv_status = 1;
232                         if (mbox_cmd.fn)
233                                 mbox_cmd.fn(mbox->lio_dev, &mbox_cmd,
234                                             mbox_cmd.fn_arg);
235
236                         return 0;
237                 }
238
239                 mbox->state = LIO_MBOX_STATE_IDLE;
240                 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
241
242                 return 0;
243         }
244
245         if (mbox->state & LIO_MBOX_STATE_RES_RECEIVED) {
246                 rte_memcpy(&mbox_cmd, &mbox->mbox_resp,
247                            sizeof(struct lio_mbox_cmd));
248                 mbox->state = LIO_MBOX_STATE_IDLE;
249                 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
250                 mbox_cmd.recv_status = 0;
251                 if (mbox_cmd.fn)
252                         mbox_cmd.fn(mbox->lio_dev, &mbox_cmd, mbox_cmd.fn_arg);
253
254                 return 0;
255         }
256
257         if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVED) {
258                 rte_memcpy(&mbox_cmd, &mbox->mbox_req,
259                            sizeof(struct lio_mbox_cmd));
260                 if (!mbox_cmd.msg.s.resp_needed) {
261                         mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVED;
262                         if (!(mbox->state & LIO_MBOX_STATE_RES_PENDING))
263                                 mbox->state = LIO_MBOX_STATE_IDLE;
264                         rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
265                 }
266
267                 lio_mbox_process_cmd(mbox, &mbox_cmd);
268
269                 return 0;
270         }
271
272         RTE_ASSERT(0);
273
274         return 0;
275 }