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