xref: /freebsd/sys/dev/qat/qat_common/adf_pfvf_vf_proto.c (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include <linux/kernel.h>
5 #include "adf_accel_devices.h"
6 #include "adf_common_drv.h"
7 #include "adf_pfvf_msg.h"
8 #include "adf_pfvf_utils.h"
9 #include "adf_pfvf_vf_msg.h"
10 #include "adf_pfvf_vf_proto.h"
11 
12 #define __bf_shf(x) (__builtin_ffsll(x) - 1)
13 
14 #define FIELD_MAX(_mask) ({ (typeof(_mask))((_mask) >> __bf_shf(_mask)); })
15 
16 #define FIELD_PREP(_mask, _val)                                                \
17 	({ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); })
18 
19 #define FIELD_GET(_mask, _reg)                                                 \
20 	({ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); })
21 
22 /**
23  * adf_send_vf2pf_msg() - send VF to PF message
24  * @accel_dev:	Pointer to acceleration device
25  * @msg:	Message to send
26  *
27  * This function allows the VF to send a message to the PF.
28  *
29  * Return: 0 on success, error code otherwise.
30  */
31 int
32 adf_send_vf2pf_msg(struct adf_accel_dev *accel_dev, struct pfvf_message msg)
33 {
34 	struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
35 	u32 pfvf_offset = pfvf_ops->get_pf2vf_offset(0);
36 
37 	int ret = pfvf_ops->send_msg(accel_dev,
38 				     msg,
39 				     pfvf_offset,
40 				     &accel_dev->u1.vf.vf2pf_lock);
41 	return ret;
42 }
43 
44 /**
45  * adf_recv_pf2vf_msg() - receive a PF to VF message
46  * @accel_dev:	Pointer to acceleration device
47  *
48  * This function allows the VF to receive a message from the PF.
49  *
50  * Return: a valid message on success, zero otherwise.
51  */
52 static struct pfvf_message
53 adf_recv_pf2vf_msg(struct adf_accel_dev *accel_dev)
54 {
55 	struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
56 	u32 pfvf_offset = pfvf_ops->get_vf2pf_offset(0); // 1008
57 	return pfvf_ops->recv_msg(accel_dev,
58 				  pfvf_offset,
59 				  accel_dev->u1.vf.pf_compat_ver);
60 }
61 
62 /**
63  * adf_send_vf2pf_req() - send VF2PF request message
64  * @accel_dev:	Pointer to acceleration device.
65  * @msg:	Request message to send
66  * @resp:	Returned PF response
67  *
68  * This function sends a message that requires a response from the VF to the PF
69  * and waits for a reply.
70  *
71  * Return: 0 on success, error code otherwise.
72  */
73 int
74 adf_send_vf2pf_req(struct adf_accel_dev *accel_dev,
75 		   struct pfvf_message msg,
76 		   struct pfvf_message *resp)
77 {
78 	unsigned long timeout = msecs_to_jiffies(ADF_PFVF_MSG_RESP_TIMEOUT);
79 	unsigned int retries = ADF_PFVF_MSG_RESP_RETRIES;
80 	int ret;
81 
82 	reinit_completion(&accel_dev->u1.vf.msg_received);
83 	/* Send request from VF to PF */
84 	do {
85 		ret = adf_send_vf2pf_msg(accel_dev, msg);
86 		if (ret) {
87 			device_printf(GET_DEV(accel_dev),
88 				      "Failed to send request msg to PF\n");
89 			return ret;
90 		}
91 
92 		/* Wait for response, if it times out retry */
93 		ret =
94 		    wait_for_completion_timeout(&accel_dev->u1.vf.msg_received,
95 						timeout);
96 		if (ret) {
97 			if (likely(resp))
98 				*resp = accel_dev->u1.vf.response;
99 
100 			/* Once copied, set to an invalid value */
101 			accel_dev->u1.vf.response.type = 0;
102 
103 			return 0;
104 		}
105 
106 		device_printf(GET_DEV(accel_dev),
107 			      "PFVF response message timeout\n");
108 	} while (--retries);
109 
110 	return -EIO;
111 }
112 
113 static int
114 adf_vf2pf_blkmsg_data_req(struct adf_accel_dev *accel_dev,
115 			  bool crc,
116 			  u8 *type,
117 			  u8 *data)
118 {
119 	struct pfvf_message req = { 0 };
120 	struct pfvf_message resp = { 0 };
121 	u8 blk_type;
122 	u8 blk_byte;
123 	u8 msg_type;
124 	u8 max_data;
125 	int err;
126 
127 	/* Convert the block type to {small, medium, large} size category */
128 	if (*type <= ADF_VF2PF_SMALL_BLOCK_TYPE_MAX) {
129 		msg_type = ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ;
130 		blk_type = FIELD_PREP(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK, *type);
131 		blk_byte = FIELD_PREP(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, *data);
132 		max_data = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX;
133 	} else if (*type <= ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX) {
134 		msg_type = ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ;
135 		blk_type = FIELD_PREP(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK,
136 				      *type - ADF_VF2PF_SMALL_BLOCK_TYPE_MAX);
137 		blk_byte = FIELD_PREP(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK, *data);
138 		max_data = ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX;
139 	} else if (*type <= ADF_VF2PF_LARGE_BLOCK_TYPE_MAX) {
140 		msg_type = ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ;
141 		blk_type = FIELD_PREP(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK,
142 				      *type - ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX);
143 		blk_byte = FIELD_PREP(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK, *data);
144 		max_data = ADF_VF2PF_LARGE_BLOCK_BYTE_MAX;
145 	} else {
146 		device_printf(GET_DEV(accel_dev),
147 			      "Invalid message type %u\n",
148 			      *type);
149 		return -EINVAL;
150 	}
151 
152 	/* Sanity check */
153 	if (*data > max_data) {
154 		device_printf(GET_DEV(accel_dev),
155 			      "Invalid byte %s %u for message type %u\n",
156 			      crc ? "count" : "index",
157 			      *data,
158 			      *type);
159 		return -EINVAL;
160 	}
161 
162 	/* Build the block message */
163 	req.type = msg_type;
164 	req.data =
165 	    blk_type | blk_byte | FIELD_PREP(ADF_VF2PF_BLOCK_CRC_REQ_MASK, crc);
166 
167 	err = adf_send_vf2pf_req(accel_dev, req, &resp);
168 	if (err)
169 		return err;
170 
171 	*type = FIELD_GET(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, resp.data);
172 	*data = FIELD_GET(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, resp.data);
173 
174 	return 0;
175 }
176 
177 static int
178 adf_vf2pf_blkmsg_get_byte(struct adf_accel_dev *accel_dev,
179 			  u8 type,
180 			  u8 index,
181 			  u8 *data)
182 {
183 	int ret;
184 
185 	ret = adf_vf2pf_blkmsg_data_req(accel_dev, false, &type, &index);
186 	if (ret < 0)
187 		return ret;
188 
189 	if (unlikely(type != ADF_PF2VF_BLKMSG_RESP_TYPE_DATA)) {
190 		device_printf(GET_DEV(accel_dev),
191 			      "Unexpected BLKMSG response type %u, byte 0x%x\n",
192 			      type,
193 			      index);
194 		return -EFAULT;
195 	}
196 
197 	*data = index;
198 	return 0;
199 }
200 
201 static int
202 adf_vf2pf_blkmsg_get_crc(struct adf_accel_dev *accel_dev,
203 			 u8 type,
204 			 u8 bytes,
205 			 u8 *crc)
206 {
207 	int ret;
208 
209 	/* The count of bytes refers to a length, however shift it to a 0-based
210 	 * count to avoid overflows. Thus, a request for 0 bytes is technically
211 	 * valid.
212 	 */
213 	--bytes;
214 
215 	ret = adf_vf2pf_blkmsg_data_req(accel_dev, true, &type, &bytes);
216 	if (ret < 0)
217 		return ret;
218 
219 	if (unlikely(type != ADF_PF2VF_BLKMSG_RESP_TYPE_CRC)) {
220 		device_printf(
221 		    GET_DEV(accel_dev),
222 		    "Unexpected CRC BLKMSG response type %u, crc 0x%x\n",
223 		    type,
224 		    bytes);
225 		return -EFAULT;
226 	}
227 
228 	*crc = bytes;
229 	return 0;
230 }
231 
232 /**
233  * adf_send_vf2pf_blkmsg_req() - retrieve block message
234  * @accel_dev:	Pointer to acceleration VF device.
235  * @type:	The block message type, see adf_pfvf_msg.h for allowed values
236  * @buffer:	input buffer where to place the received data
237  * @buffer_len:	buffer length as input, the amount of written bytes on output
238  *
239  * Request a message of type 'type' over the block message transport.
240  * This function will send the required amount block message requests and
241  * return the overall content back to the caller through the provided buffer.
242  * The buffer should be large enough to contain the requested message type,
243  * otherwise the response will be truncated.
244  *
245  * Return: 0 on success, error code otherwise.
246  */
247 int
248 adf_send_vf2pf_blkmsg_req(struct adf_accel_dev *accel_dev,
249 			  u8 type,
250 			  u8 *buffer,
251 			  unsigned int *buffer_len)
252 {
253 	unsigned int index;
254 	unsigned int msg_len;
255 	int ret;
256 	u8 remote_crc;
257 	u8 local_crc;
258 
259 	if (unlikely(type > ADF_VF2PF_LARGE_BLOCK_TYPE_MAX)) {
260 		device_printf(GET_DEV(accel_dev),
261 			      "Invalid block message type %d\n",
262 			      type);
263 		return -EINVAL;
264 	}
265 
266 	if (unlikely(*buffer_len < ADF_PFVF_BLKMSG_HEADER_SIZE)) {
267 		device_printf(GET_DEV(accel_dev),
268 			      "Buffer size too small for a block message\n");
269 		return -EINVAL;
270 	}
271 
272 	ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
273 					type,
274 					ADF_PFVF_BLKMSG_VER_BYTE,
275 					&buffer[ADF_PFVF_BLKMSG_VER_BYTE]);
276 	if (unlikely(ret))
277 		return ret;
278 
279 	if (unlikely(!buffer[ADF_PFVF_BLKMSG_VER_BYTE])) {
280 		device_printf(GET_DEV(accel_dev),
281 			      "Invalid version 0 received for block request %u",
282 			      type);
283 		return -EFAULT;
284 	}
285 
286 	ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
287 					type,
288 					ADF_PFVF_BLKMSG_LEN_BYTE,
289 					&buffer[ADF_PFVF_BLKMSG_LEN_BYTE]);
290 	if (unlikely(ret))
291 		return ret;
292 
293 	if (unlikely(!buffer[ADF_PFVF_BLKMSG_LEN_BYTE])) {
294 		device_printf(GET_DEV(accel_dev),
295 			      "Invalid size 0 received for block request %u",
296 			      type);
297 		return -EFAULT;
298 	}
299 
300 	/* We need to pick the minimum since there is no way to request a
301 	 * specific version. As a consequence any scenario is possible:
302 	 * - PF has a newer (longer) version which doesn't fit in the buffer
303 	 * - VF expects a newer (longer) version, so we must not ask for
304 	 *   bytes in excess
305 	 * - PF and VF share the same version, no problem
306 	 */
307 	msg_len =
308 	    ADF_PFVF_BLKMSG_HEADER_SIZE + buffer[ADF_PFVF_BLKMSG_LEN_BYTE];
309 	msg_len = min(*buffer_len, msg_len);
310 
311 	/* Get the payload */
312 	for (index = ADF_PFVF_BLKMSG_HEADER_SIZE; index < msg_len; index++) {
313 		ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
314 						type,
315 						index,
316 						&buffer[index]);
317 		if (unlikely(ret))
318 			return ret;
319 	}
320 
321 	ret = adf_vf2pf_blkmsg_get_crc(accel_dev, type, msg_len, &remote_crc);
322 	if (unlikely(ret))
323 		return ret;
324 
325 	local_crc = adf_pfvf_calc_blkmsg_crc(buffer, msg_len);
326 	if (unlikely(local_crc != remote_crc)) {
327 		device_printf(
328 		    GET_DEV(accel_dev),
329 		    "CRC error on msg type %d. Local %02X, remote %02X\n",
330 		    type,
331 		    local_crc,
332 		    remote_crc);
333 		return -EIO;
334 	}
335 
336 	*buffer_len = msg_len;
337 	return 0;
338 }
339 
340 static bool
341 adf_handle_pf2vf_msg(struct adf_accel_dev *accel_dev, struct pfvf_message msg)
342 {
343 	switch (msg.type) {
344 	case ADF_PF2VF_MSGTYPE_RESTARTING:
345 		adf_pf2vf_handle_pf_restarting(accel_dev);
346 		return false;
347 	case ADF_PF2VF_MSGTYPE_RP_RESET_RESP:
348 		adf_pf2vf_handle_pf_rp_reset(accel_dev, msg);
349 		return true;
350 	case ADF_PF2VF_MSGTYPE_VERSION_RESP:
351 	case ADF_PF2VF_MSGTYPE_BLKMSG_RESP:
352 		accel_dev->u1.vf.response = msg;
353 		complete(&accel_dev->u1.vf.msg_received);
354 		return true;
355 	default:
356 		device_printf(
357 		    GET_DEV(accel_dev),
358 		    "Unknown message from PF (type 0x%.4x, data: 0x%.4x)\n",
359 		    msg.type,
360 		    msg.data);
361 	}
362 
363 	return false;
364 }
365 
366 bool
367 adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev *accel_dev)
368 {
369 	struct pfvf_message msg;
370 
371 	msg = adf_recv_pf2vf_msg(accel_dev);
372 	if (msg.type) /* Invalid or no message */
373 		return adf_handle_pf2vf_msg(accel_dev, msg);
374 
375 	/* No replies for PF->VF messages at present */
376 
377 	return true;
378 }
379 
380 /**
381  * adf_enable_vf2pf_comms() - Function enables communication from vf to pf
382  *
383  * @accel_dev:	Pointer to acceleration device virtual function.
384  *
385  * Return: 0 on success, error code otherwise.
386  */
387 int
388 adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
389 {
390 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
391 	int ret;
392 
393 	hw_data->enable_pf2vf_interrupt(accel_dev);
394 
395 	ret = adf_vf2pf_request_version(accel_dev);
396 	if (ret)
397 		return ret;
398 
399 	ret = adf_vf2pf_get_capabilities(accel_dev);
400 	if (ret)
401 		return ret;
402 
403 	ret = adf_vf2pf_get_ring_to_svc(accel_dev);
404 	return ret;
405 }
406