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
lio_mbox_read(struct lio_mbox * mbox)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
lio_mbox_write(struct lio_device * lio_dev,struct lio_mbox_cmd * mbox_cmd)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
lio_mbox_process_cmd(struct lio_mbox * mbox,struct lio_mbox_cmd * mbox_cmd)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
lio_mbox_process_message(struct lio_mbox * mbox)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 }
247