xref: /freebsd/sys/dev/qat/qat_common/adf_pfvf_vf_proto.c (revision ded037e65e5239671b1292ec987a2e0894b217b5)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2025 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
adf_send_vf2pf_msg(struct adf_accel_dev * accel_dev,struct pfvf_message msg)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
adf_recv_pf2vf_msg(struct adf_accel_dev * accel_dev)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
adf_send_vf2pf_req(struct adf_accel_dev * accel_dev,struct pfvf_message msg,struct pfvf_message * resp)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 		if (!cold) {
93 			ret = wait_for_completion_timeout(
94 			    &accel_dev->u1.vf.msg_received, timeout);
95 		} else {
96 			/* In cold start timers may not be initialized yet */
97 			DELAY(ADF_PFVF_MSG_RESP_TIMEOUT * 1000);
98 			ret = try_wait_for_completion(
99 			    &accel_dev->u1.vf.msg_received);
100 		}
101 		if (ret) {
102 			if (likely(resp))
103 				*resp = accel_dev->u1.vf.response;
104 
105 			/* Once copied, set to an invalid value */
106 			accel_dev->u1.vf.response.type = 0;
107 
108 			return 0;
109 		}
110 
111 		device_printf(GET_DEV(accel_dev),
112 			      "PFVF response message timeout\n");
113 	} while (--retries);
114 
115 	return -EIO;
116 }
117 
118 static int
adf_vf2pf_blkmsg_data_req(struct adf_accel_dev * accel_dev,bool crc,u8 * type,u8 * data)119 adf_vf2pf_blkmsg_data_req(struct adf_accel_dev *accel_dev,
120 			  bool crc,
121 			  u8 *type,
122 			  u8 *data)
123 {
124 	struct pfvf_message req = { 0 };
125 	struct pfvf_message resp = { 0 };
126 	u8 blk_type;
127 	u8 blk_byte;
128 	u8 msg_type;
129 	u8 max_data;
130 	int err;
131 
132 	/* Convert the block type to {small, medium, large} size category */
133 	if (*type <= ADF_VF2PF_SMALL_BLOCK_TYPE_MAX) {
134 		msg_type = ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ;
135 		blk_type = FIELD_PREP(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK, *type);
136 		blk_byte = FIELD_PREP(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, *data);
137 		max_data = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX;
138 	} else if (*type <= ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX) {
139 		msg_type = ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ;
140 		blk_type = FIELD_PREP(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK,
141 				      *type - ADF_VF2PF_SMALL_BLOCK_TYPE_MAX);
142 		blk_byte = FIELD_PREP(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK, *data);
143 		max_data = ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX;
144 	} else if (*type <= ADF_VF2PF_LARGE_BLOCK_TYPE_MAX) {
145 		msg_type = ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ;
146 		blk_type = FIELD_PREP(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK,
147 				      *type - ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX);
148 		blk_byte = FIELD_PREP(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK, *data);
149 		max_data = ADF_VF2PF_LARGE_BLOCK_BYTE_MAX;
150 	} else {
151 		device_printf(GET_DEV(accel_dev),
152 			      "Invalid message type %u\n",
153 			      *type);
154 		return -EINVAL;
155 	}
156 
157 	/* Sanity check */
158 	if (*data > max_data) {
159 		device_printf(GET_DEV(accel_dev),
160 			      "Invalid byte %s %u for message type %u\n",
161 			      crc ? "count" : "index",
162 			      *data,
163 			      *type);
164 		return -EINVAL;
165 	}
166 
167 	/* Build the block message */
168 	req.type = msg_type;
169 	req.data =
170 	    blk_type | blk_byte | FIELD_PREP(ADF_VF2PF_BLOCK_CRC_REQ_MASK, crc);
171 
172 	err = adf_send_vf2pf_req(accel_dev, req, &resp);
173 	if (err)
174 		return err;
175 
176 	*type = FIELD_GET(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, resp.data);
177 	*data = FIELD_GET(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, resp.data);
178 
179 	return 0;
180 }
181 
182 static int
adf_vf2pf_blkmsg_get_byte(struct adf_accel_dev * accel_dev,u8 type,u8 index,u8 * data)183 adf_vf2pf_blkmsg_get_byte(struct adf_accel_dev *accel_dev,
184 			  u8 type,
185 			  u8 index,
186 			  u8 *data)
187 {
188 	int ret;
189 
190 	ret = adf_vf2pf_blkmsg_data_req(accel_dev, false, &type, &index);
191 	if (ret < 0)
192 		return ret;
193 
194 	if (unlikely(type != ADF_PF2VF_BLKMSG_RESP_TYPE_DATA)) {
195 		device_printf(GET_DEV(accel_dev),
196 			      "Unexpected BLKMSG response type %u, byte 0x%x\n",
197 			      type,
198 			      index);
199 		return -EFAULT;
200 	}
201 
202 	*data = index;
203 	return 0;
204 }
205 
206 static int
adf_vf2pf_blkmsg_get_crc(struct adf_accel_dev * accel_dev,u8 type,u8 bytes,u8 * crc)207 adf_vf2pf_blkmsg_get_crc(struct adf_accel_dev *accel_dev,
208 			 u8 type,
209 			 u8 bytes,
210 			 u8 *crc)
211 {
212 	int ret;
213 
214 	/* The count of bytes refers to a length, however shift it to a 0-based
215 	 * count to avoid overflows. Thus, a request for 0 bytes is technically
216 	 * valid.
217 	 */
218 	--bytes;
219 
220 	ret = adf_vf2pf_blkmsg_data_req(accel_dev, true, &type, &bytes);
221 	if (ret < 0)
222 		return ret;
223 
224 	if (unlikely(type != ADF_PF2VF_BLKMSG_RESP_TYPE_CRC)) {
225 		device_printf(
226 		    GET_DEV(accel_dev),
227 		    "Unexpected CRC BLKMSG response type %u, crc 0x%x\n",
228 		    type,
229 		    bytes);
230 		return -EFAULT;
231 	}
232 
233 	*crc = bytes;
234 	return 0;
235 }
236 
237 /**
238  * adf_send_vf2pf_blkmsg_req() - retrieve block message
239  * @accel_dev:	Pointer to acceleration VF device.
240  * @type:	The block message type, see adf_pfvf_msg.h for allowed values
241  * @buffer:	input buffer where to place the received data
242  * @buffer_len:	buffer length as input, the amount of written bytes on output
243  *
244  * Request a message of type 'type' over the block message transport.
245  * This function will send the required amount block message requests and
246  * return the overall content back to the caller through the provided buffer.
247  * The buffer should be large enough to contain the requested message type,
248  * otherwise the response will be truncated.
249  *
250  * Return: 0 on success, error code otherwise.
251  */
252 int
adf_send_vf2pf_blkmsg_req(struct adf_accel_dev * accel_dev,u8 type,u8 * buffer,unsigned int * buffer_len)253 adf_send_vf2pf_blkmsg_req(struct adf_accel_dev *accel_dev,
254 			  u8 type,
255 			  u8 *buffer,
256 			  unsigned int *buffer_len)
257 {
258 	unsigned int index;
259 	unsigned int msg_len;
260 	int ret;
261 	u8 remote_crc;
262 	u8 local_crc;
263 
264 	if (unlikely(type > ADF_VF2PF_LARGE_BLOCK_TYPE_MAX)) {
265 		device_printf(GET_DEV(accel_dev),
266 			      "Invalid block message type %d\n",
267 			      type);
268 		return -EINVAL;
269 	}
270 
271 	if (unlikely(*buffer_len < ADF_PFVF_BLKMSG_HEADER_SIZE)) {
272 		device_printf(GET_DEV(accel_dev),
273 			      "Buffer size too small for a block message\n");
274 		return -EINVAL;
275 	}
276 
277 	ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
278 					type,
279 					ADF_PFVF_BLKMSG_VER_BYTE,
280 					&buffer[ADF_PFVF_BLKMSG_VER_BYTE]);
281 	if (unlikely(ret))
282 		return ret;
283 
284 	if (unlikely(!buffer[ADF_PFVF_BLKMSG_VER_BYTE])) {
285 		device_printf(GET_DEV(accel_dev),
286 			      "Invalid version 0 received for block request %u",
287 			      type);
288 		return -EFAULT;
289 	}
290 
291 	ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
292 					type,
293 					ADF_PFVF_BLKMSG_LEN_BYTE,
294 					&buffer[ADF_PFVF_BLKMSG_LEN_BYTE]);
295 	if (unlikely(ret))
296 		return ret;
297 
298 	if (unlikely(!buffer[ADF_PFVF_BLKMSG_LEN_BYTE])) {
299 		device_printf(GET_DEV(accel_dev),
300 			      "Invalid size 0 received for block request %u",
301 			      type);
302 		return -EFAULT;
303 	}
304 
305 	/* We need to pick the minimum since there is no way to request a
306 	 * specific version. As a consequence any scenario is possible:
307 	 * - PF has a newer (longer) version which doesn't fit in the buffer
308 	 * - VF expects a newer (longer) version, so we must not ask for
309 	 *   bytes in excess
310 	 * - PF and VF share the same version, no problem
311 	 */
312 	msg_len =
313 	    ADF_PFVF_BLKMSG_HEADER_SIZE + buffer[ADF_PFVF_BLKMSG_LEN_BYTE];
314 	msg_len = min(*buffer_len, msg_len);
315 
316 	/* Get the payload */
317 	for (index = ADF_PFVF_BLKMSG_HEADER_SIZE; index < msg_len; index++) {
318 		ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
319 						type,
320 						index,
321 						&buffer[index]);
322 		if (unlikely(ret))
323 			return ret;
324 	}
325 
326 	ret = adf_vf2pf_blkmsg_get_crc(accel_dev, type, msg_len, &remote_crc);
327 	if (unlikely(ret))
328 		return ret;
329 
330 	local_crc = adf_pfvf_calc_blkmsg_crc(buffer, msg_len);
331 	if (unlikely(local_crc != remote_crc)) {
332 		device_printf(
333 		    GET_DEV(accel_dev),
334 		    "CRC error on msg type %d. Local %02X, remote %02X\n",
335 		    type,
336 		    local_crc,
337 		    remote_crc);
338 		return -EIO;
339 	}
340 
341 	*buffer_len = msg_len;
342 	return 0;
343 }
344 
345 static bool
adf_handle_pf2vf_msg(struct adf_accel_dev * accel_dev,struct pfvf_message msg)346 adf_handle_pf2vf_msg(struct adf_accel_dev *accel_dev, struct pfvf_message msg)
347 {
348 	switch (msg.type) {
349 	case ADF_PF2VF_MSGTYPE_RESTARTING:
350 		adf_pf2vf_handle_pf_restarting(accel_dev);
351 		return false;
352 	case ADF_PF2VF_MSGTYPE_RP_RESET_RESP:
353 		adf_pf2vf_handle_pf_rp_reset(accel_dev, msg);
354 		return true;
355 	case ADF_PF2VF_MSGTYPE_FATAL_ERROR:
356 		adf_pf2vf_handle_pf_error(accel_dev);
357 		return true;
358 	case ADF_PF2VF_MSGTYPE_VERSION_RESP:
359 	case ADF_PF2VF_MSGTYPE_BLKMSG_RESP:
360 		accel_dev->u1.vf.response = msg;
361 		complete(&accel_dev->u1.vf.msg_received);
362 		return true;
363 	default:
364 		device_printf(
365 		    GET_DEV(accel_dev),
366 		    "Unknown message from PF (type 0x%.4x, data: 0x%.4x)\n",
367 		    msg.type,
368 		    msg.data);
369 	}
370 
371 	return false;
372 }
373 
374 bool
adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev * accel_dev)375 adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev *accel_dev)
376 {
377 	struct pfvf_message msg;
378 
379 	msg = adf_recv_pf2vf_msg(accel_dev);
380 	if (msg.type) /* Invalid or no message */
381 		return adf_handle_pf2vf_msg(accel_dev, msg);
382 
383 	/* No replies for PF->VF messages at present */
384 
385 	return true;
386 }
387 
388 /**
389  * adf_enable_vf2pf_comms() - Function enables communication from vf to pf
390  *
391  * @accel_dev:	Pointer to acceleration device virtual function.
392  *
393  * Return: 0 on success, error code otherwise.
394  */
395 int
adf_enable_vf2pf_comms(struct adf_accel_dev * accel_dev)396 adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
397 {
398 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
399 	int ret;
400 
401 	/* init workqueue for VF */
402 	ret = adf_init_vf_wq();
403 	if (ret)
404 		return ret;
405 
406 	hw_data->enable_pf2vf_interrupt(accel_dev);
407 
408 	ret = adf_vf2pf_request_version(accel_dev);
409 	if (ret)
410 		return ret;
411 
412 	ret = adf_vf2pf_get_capabilities(accel_dev);
413 	if (ret)
414 		return ret;
415 
416 	ret = adf_vf2pf_get_ring_to_svc(accel_dev);
417 	return ret;
418 }
419