New upstream version 18.02
[deb_dpdk.git] / drivers / net / liquidio / base / lio_mbox.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Cavium, Inc
3  */
4
5 #include <rte_ethdev_driver.h>
6 #include <rte_cycles.h>
7
8 #include "lio_logs.h"
9 #include "lio_struct.h"
10 #include "lio_mbox.h"
11
12 /**
13  * lio_mbox_read:
14  * @mbox: Pointer mailbox
15  *
16  * Reads the 8-bytes of data from the mbox register
17  * Writes back the acknowledgment indicating completion of read
18  */
19 int
20 lio_mbox_read(struct lio_mbox *mbox)
21 {
22         union lio_mbox_message msg;
23         int ret = 0;
24
25         msg.mbox_msg64 = rte_read64(mbox->mbox_read_reg);
26
27         if ((msg.mbox_msg64 == LIO_PFVFACK) || (msg.mbox_msg64 == LIO_PFVFSIG))
28                 return 0;
29
30         if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) {
31                 mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] =
32                                         msg.mbox_msg64;
33                 mbox->mbox_req.recv_len++;
34         } else {
35                 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) {
36                         mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
37                                         msg.mbox_msg64;
38                         mbox->mbox_resp.recv_len++;
39                 } else {
40                         if ((mbox->state & LIO_MBOX_STATE_IDLE) &&
41                                         (msg.s.type == LIO_MBOX_REQUEST)) {
42                                 mbox->state &= ~LIO_MBOX_STATE_IDLE;
43                                 mbox->state |= LIO_MBOX_STATE_REQ_RECEIVING;
44                                 mbox->mbox_req.msg.mbox_msg64 = msg.mbox_msg64;
45                                 mbox->mbox_req.q_no = mbox->q_no;
46                                 mbox->mbox_req.recv_len = 1;
47                         } else {
48                                 if ((mbox->state &
49                                      LIO_MBOX_STATE_RES_PENDING) &&
50                                     (msg.s.type == LIO_MBOX_RESPONSE)) {
51                                         mbox->state &=
52                                                 ~LIO_MBOX_STATE_RES_PENDING;
53                                         mbox->state |=
54                                                 LIO_MBOX_STATE_RES_RECEIVING;
55                                         mbox->mbox_resp.msg.mbox_msg64 =
56                                                                 msg.mbox_msg64;
57                                         mbox->mbox_resp.q_no = mbox->q_no;
58                                         mbox->mbox_resp.recv_len = 1;
59                                 } else {
60                                         rte_write64(LIO_PFVFERR,
61                                                     mbox->mbox_read_reg);
62                                         mbox->state |= LIO_MBOX_STATE_ERROR;
63                                         return -1;
64                                 }
65                         }
66                 }
67         }
68
69         if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) {
70                 if (mbox->mbox_req.recv_len < msg.s.len) {
71                         ret = 0;
72                 } else {
73                         mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVING;
74                         mbox->state |= LIO_MBOX_STATE_REQ_RECEIVED;
75                         ret = 1;
76                 }
77         } else {
78                 if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) {
79                         if (mbox->mbox_resp.recv_len < msg.s.len) {
80                                 ret = 0;
81                         } else {
82                                 mbox->state &= ~LIO_MBOX_STATE_RES_RECEIVING;
83                                 mbox->state |= LIO_MBOX_STATE_RES_RECEIVED;
84                                 ret = 1;
85                         }
86                 } else {
87                         RTE_ASSERT(0);
88                 }
89         }
90
91         rte_write64(LIO_PFVFACK, mbox->mbox_read_reg);
92
93         return ret;
94 }
95
96 /**
97  * lio_mbox_write:
98  * @lio_dev: Pointer lio device
99  * @mbox_cmd: Cmd to send to mailbox.
100  *
101  * Populates the queue specific mbox structure
102  * with cmd information.
103  * Write the cmd to mbox register
104  */
105 int
106 lio_mbox_write(struct lio_device *lio_dev,
107                struct lio_mbox_cmd *mbox_cmd)
108 {
109         struct lio_mbox *mbox = lio_dev->mbox[mbox_cmd->q_no];
110         uint32_t count, i, ret = LIO_MBOX_STATUS_SUCCESS;
111
112         if ((mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) &&
113                         !(mbox->state & LIO_MBOX_STATE_REQ_RECEIVED))
114                 return LIO_MBOX_STATUS_FAILED;
115
116         if ((mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) &&
117                         !(mbox->state & LIO_MBOX_STATE_IDLE))
118                 return LIO_MBOX_STATUS_BUSY;
119
120         if (mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) {
121                 rte_memcpy(&mbox->mbox_resp, mbox_cmd,
122                            sizeof(struct lio_mbox_cmd));
123                 mbox->state = LIO_MBOX_STATE_RES_PENDING;
124         }
125
126         count = 0;
127
128         while (rte_read64(mbox->mbox_write_reg) != LIO_PFVFSIG) {
129                 rte_delay_ms(1);
130                 if (count++ == 1000) {
131                         ret = LIO_MBOX_STATUS_FAILED;
132                         break;
133                 }
134         }
135
136         if (ret == LIO_MBOX_STATUS_SUCCESS) {
137                 rte_write64(mbox_cmd->msg.mbox_msg64, mbox->mbox_write_reg);
138                 for (i = 0; i < (uint32_t)(mbox_cmd->msg.s.len - 1); i++) {
139                         count = 0;
140                         while (rte_read64(mbox->mbox_write_reg) !=
141                                         LIO_PFVFACK) {
142                                 rte_delay_ms(1);
143                                 if (count++ == 1000) {
144                                         ret = LIO_MBOX_STATUS_FAILED;
145                                         break;
146                                 }
147                         }
148                         rte_write64(mbox_cmd->data[i], mbox->mbox_write_reg);
149                 }
150         }
151
152         if (mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) {
153                 mbox->state = LIO_MBOX_STATE_IDLE;
154                 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
155         } else {
156                 if ((!mbox_cmd->msg.s.resp_needed) ||
157                                 (ret == LIO_MBOX_STATUS_FAILED)) {
158                         mbox->state &= ~LIO_MBOX_STATE_RES_PENDING;
159                         if (!(mbox->state & (LIO_MBOX_STATE_REQ_RECEIVING |
160                                              LIO_MBOX_STATE_REQ_RECEIVED)))
161                                 mbox->state = LIO_MBOX_STATE_IDLE;
162                 }
163         }
164
165         return ret;
166 }
167
168 /**
169  * lio_mbox_process_cmd:
170  * @mbox: Pointer mailbox
171  * @mbox_cmd: Pointer to command received
172  *
173  * Process the cmd received in mbox
174  */
175 static int
176 lio_mbox_process_cmd(struct lio_mbox *mbox,
177                      struct lio_mbox_cmd *mbox_cmd)
178 {
179         struct lio_device *lio_dev = mbox->lio_dev;
180
181         if (mbox_cmd->msg.s.cmd == LIO_CORES_CRASHED)
182                 lio_dev_err(lio_dev, "Octeon core(s) crashed or got stuck!\n");
183
184         return 0;
185 }
186
187 /**
188  * Process the received mbox message.
189  */
190 int
191 lio_mbox_process_message(struct lio_mbox *mbox)
192 {
193         struct lio_mbox_cmd mbox_cmd;
194
195         if (mbox->state & LIO_MBOX_STATE_ERROR) {
196                 if (mbox->state & (LIO_MBOX_STATE_RES_PENDING |
197                                    LIO_MBOX_STATE_RES_RECEIVING)) {
198                         rte_memcpy(&mbox_cmd, &mbox->mbox_resp,
199                                    sizeof(struct lio_mbox_cmd));
200                         mbox->state = LIO_MBOX_STATE_IDLE;
201                         rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
202                         mbox_cmd.recv_status = 1;
203                         if (mbox_cmd.fn)
204                                 mbox_cmd.fn(mbox->lio_dev, &mbox_cmd,
205                                             mbox_cmd.fn_arg);
206
207                         return 0;
208                 }
209
210                 mbox->state = LIO_MBOX_STATE_IDLE;
211                 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
212
213                 return 0;
214         }
215
216         if (mbox->state & LIO_MBOX_STATE_RES_RECEIVED) {
217                 rte_memcpy(&mbox_cmd, &mbox->mbox_resp,
218                            sizeof(struct lio_mbox_cmd));
219                 mbox->state = LIO_MBOX_STATE_IDLE;
220                 rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
221                 mbox_cmd.recv_status = 0;
222                 if (mbox_cmd.fn)
223                         mbox_cmd.fn(mbox->lio_dev, &mbox_cmd, mbox_cmd.fn_arg);
224
225                 return 0;
226         }
227
228         if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVED) {
229                 rte_memcpy(&mbox_cmd, &mbox->mbox_req,
230                            sizeof(struct lio_mbox_cmd));
231                 if (!mbox_cmd.msg.s.resp_needed) {
232                         mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVED;
233                         if (!(mbox->state & LIO_MBOX_STATE_RES_PENDING))
234                                 mbox->state = LIO_MBOX_STATE_IDLE;
235                         rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg);
236                 }
237
238                 lio_mbox_process_cmd(mbox, &mbox_cmd);
239
240                 return 0;
241         }
242
243         RTE_ASSERT(0);
244
245         return 0;
246 }