xref: /freebsd/sys/dev/qat/qat_common/adf_pfvf_vf_proto.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1266b0663SKrzysztof Zdziarski /* SPDX-License-Identifier: BSD-3-Clause */
2266b0663SKrzysztof Zdziarski /* Copyright(c) 2007-2022 Intel Corporation */
3266b0663SKrzysztof Zdziarski #include <linux/kernel.h>
4266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h"
5266b0663SKrzysztof Zdziarski #include "adf_common_drv.h"
6266b0663SKrzysztof Zdziarski #include "adf_pfvf_msg.h"
7266b0663SKrzysztof Zdziarski #include "adf_pfvf_utils.h"
8266b0663SKrzysztof Zdziarski #include "adf_pfvf_vf_msg.h"
9266b0663SKrzysztof Zdziarski #include "adf_pfvf_vf_proto.h"
10266b0663SKrzysztof Zdziarski 
11266b0663SKrzysztof Zdziarski #define __bf_shf(x) (__builtin_ffsll(x) - 1)
12266b0663SKrzysztof Zdziarski 
13266b0663SKrzysztof Zdziarski #define FIELD_MAX(_mask) ({ (typeof(_mask))((_mask) >> __bf_shf(_mask)); })
14266b0663SKrzysztof Zdziarski 
15266b0663SKrzysztof Zdziarski #define FIELD_PREP(_mask, _val)                                                \
16266b0663SKrzysztof Zdziarski 	({ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); })
17266b0663SKrzysztof Zdziarski 
18266b0663SKrzysztof Zdziarski #define FIELD_GET(_mask, _reg)                                                 \
19266b0663SKrzysztof Zdziarski 	({ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); })
20266b0663SKrzysztof Zdziarski 
21266b0663SKrzysztof Zdziarski /**
22266b0663SKrzysztof Zdziarski  * adf_send_vf2pf_msg() - send VF to PF message
23266b0663SKrzysztof Zdziarski  * @accel_dev:	Pointer to acceleration device
24266b0663SKrzysztof Zdziarski  * @msg:	Message to send
25266b0663SKrzysztof Zdziarski  *
26266b0663SKrzysztof Zdziarski  * This function allows the VF to send a message to the PF.
27266b0663SKrzysztof Zdziarski  *
28266b0663SKrzysztof Zdziarski  * Return: 0 on success, error code otherwise.
29266b0663SKrzysztof Zdziarski  */
30266b0663SKrzysztof Zdziarski int
adf_send_vf2pf_msg(struct adf_accel_dev * accel_dev,struct pfvf_message msg)31266b0663SKrzysztof Zdziarski adf_send_vf2pf_msg(struct adf_accel_dev *accel_dev, struct pfvf_message msg)
32266b0663SKrzysztof Zdziarski {
33266b0663SKrzysztof Zdziarski 	struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
34266b0663SKrzysztof Zdziarski 	u32 pfvf_offset = pfvf_ops->get_pf2vf_offset(0);
35266b0663SKrzysztof Zdziarski 
36266b0663SKrzysztof Zdziarski 	int ret = pfvf_ops->send_msg(accel_dev,
37266b0663SKrzysztof Zdziarski 				     msg,
38266b0663SKrzysztof Zdziarski 				     pfvf_offset,
39266b0663SKrzysztof Zdziarski 				     &accel_dev->u1.vf.vf2pf_lock);
40266b0663SKrzysztof Zdziarski 	return ret;
41266b0663SKrzysztof Zdziarski }
42266b0663SKrzysztof Zdziarski 
43266b0663SKrzysztof Zdziarski /**
44266b0663SKrzysztof Zdziarski  * adf_recv_pf2vf_msg() - receive a PF to VF message
45266b0663SKrzysztof Zdziarski  * @accel_dev:	Pointer to acceleration device
46266b0663SKrzysztof Zdziarski  *
47266b0663SKrzysztof Zdziarski  * This function allows the VF to receive a message from the PF.
48266b0663SKrzysztof Zdziarski  *
49266b0663SKrzysztof Zdziarski  * Return: a valid message on success, zero otherwise.
50266b0663SKrzysztof Zdziarski  */
51266b0663SKrzysztof Zdziarski static struct pfvf_message
adf_recv_pf2vf_msg(struct adf_accel_dev * accel_dev)52266b0663SKrzysztof Zdziarski adf_recv_pf2vf_msg(struct adf_accel_dev *accel_dev)
53266b0663SKrzysztof Zdziarski {
54266b0663SKrzysztof Zdziarski 	struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
55266b0663SKrzysztof Zdziarski 	u32 pfvf_offset = pfvf_ops->get_vf2pf_offset(0); // 1008
56266b0663SKrzysztof Zdziarski 	return pfvf_ops->recv_msg(accel_dev,
57266b0663SKrzysztof Zdziarski 				  pfvf_offset,
58266b0663SKrzysztof Zdziarski 				  accel_dev->u1.vf.pf_compat_ver);
59266b0663SKrzysztof Zdziarski }
60266b0663SKrzysztof Zdziarski 
61266b0663SKrzysztof Zdziarski /**
62266b0663SKrzysztof Zdziarski  * adf_send_vf2pf_req() - send VF2PF request message
63266b0663SKrzysztof Zdziarski  * @accel_dev:	Pointer to acceleration device.
64266b0663SKrzysztof Zdziarski  * @msg:	Request message to send
65266b0663SKrzysztof Zdziarski  * @resp:	Returned PF response
66266b0663SKrzysztof Zdziarski  *
67266b0663SKrzysztof Zdziarski  * This function sends a message that requires a response from the VF to the PF
68266b0663SKrzysztof Zdziarski  * and waits for a reply.
69266b0663SKrzysztof Zdziarski  *
70266b0663SKrzysztof Zdziarski  * Return: 0 on success, error code otherwise.
71266b0663SKrzysztof Zdziarski  */
72266b0663SKrzysztof Zdziarski int
adf_send_vf2pf_req(struct adf_accel_dev * accel_dev,struct pfvf_message msg,struct pfvf_message * resp)73266b0663SKrzysztof Zdziarski adf_send_vf2pf_req(struct adf_accel_dev *accel_dev,
74266b0663SKrzysztof Zdziarski 		   struct pfvf_message msg,
75266b0663SKrzysztof Zdziarski 		   struct pfvf_message *resp)
76266b0663SKrzysztof Zdziarski {
77266b0663SKrzysztof Zdziarski 	unsigned long timeout = msecs_to_jiffies(ADF_PFVF_MSG_RESP_TIMEOUT);
78266b0663SKrzysztof Zdziarski 	unsigned int retries = ADF_PFVF_MSG_RESP_RETRIES;
79266b0663SKrzysztof Zdziarski 	int ret;
80266b0663SKrzysztof Zdziarski 
81266b0663SKrzysztof Zdziarski 	reinit_completion(&accel_dev->u1.vf.msg_received);
82266b0663SKrzysztof Zdziarski 	/* Send request from VF to PF */
83266b0663SKrzysztof Zdziarski 	do {
84266b0663SKrzysztof Zdziarski 		ret = adf_send_vf2pf_msg(accel_dev, msg);
85266b0663SKrzysztof Zdziarski 		if (ret) {
86266b0663SKrzysztof Zdziarski 			device_printf(GET_DEV(accel_dev),
87266b0663SKrzysztof Zdziarski 				      "Failed to send request msg to PF\n");
88266b0663SKrzysztof Zdziarski 			return ret;
89266b0663SKrzysztof Zdziarski 		}
90266b0663SKrzysztof Zdziarski 
91266b0663SKrzysztof Zdziarski 		/* Wait for response, if it times out retry */
92266b0663SKrzysztof Zdziarski 		ret =
93266b0663SKrzysztof Zdziarski 		    wait_for_completion_timeout(&accel_dev->u1.vf.msg_received,
94266b0663SKrzysztof Zdziarski 						timeout);
95266b0663SKrzysztof Zdziarski 		if (ret) {
96266b0663SKrzysztof Zdziarski 			if (likely(resp))
97266b0663SKrzysztof Zdziarski 				*resp = accel_dev->u1.vf.response;
98266b0663SKrzysztof Zdziarski 
99266b0663SKrzysztof Zdziarski 			/* Once copied, set to an invalid value */
100266b0663SKrzysztof Zdziarski 			accel_dev->u1.vf.response.type = 0;
101266b0663SKrzysztof Zdziarski 
102266b0663SKrzysztof Zdziarski 			return 0;
103266b0663SKrzysztof Zdziarski 		}
104266b0663SKrzysztof Zdziarski 
105266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
106266b0663SKrzysztof Zdziarski 			      "PFVF response message timeout\n");
107266b0663SKrzysztof Zdziarski 	} while (--retries);
108266b0663SKrzysztof Zdziarski 
109266b0663SKrzysztof Zdziarski 	return -EIO;
110266b0663SKrzysztof Zdziarski }
111266b0663SKrzysztof Zdziarski 
112266b0663SKrzysztof Zdziarski static int
adf_vf2pf_blkmsg_data_req(struct adf_accel_dev * accel_dev,bool crc,u8 * type,u8 * data)113266b0663SKrzysztof Zdziarski adf_vf2pf_blkmsg_data_req(struct adf_accel_dev *accel_dev,
114266b0663SKrzysztof Zdziarski 			  bool crc,
115266b0663SKrzysztof Zdziarski 			  u8 *type,
116266b0663SKrzysztof Zdziarski 			  u8 *data)
117266b0663SKrzysztof Zdziarski {
118266b0663SKrzysztof Zdziarski 	struct pfvf_message req = { 0 };
119266b0663SKrzysztof Zdziarski 	struct pfvf_message resp = { 0 };
120266b0663SKrzysztof Zdziarski 	u8 blk_type;
121266b0663SKrzysztof Zdziarski 	u8 blk_byte;
122266b0663SKrzysztof Zdziarski 	u8 msg_type;
123266b0663SKrzysztof Zdziarski 	u8 max_data;
124266b0663SKrzysztof Zdziarski 	int err;
125266b0663SKrzysztof Zdziarski 
126266b0663SKrzysztof Zdziarski 	/* Convert the block type to {small, medium, large} size category */
127266b0663SKrzysztof Zdziarski 	if (*type <= ADF_VF2PF_SMALL_BLOCK_TYPE_MAX) {
128266b0663SKrzysztof Zdziarski 		msg_type = ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ;
129266b0663SKrzysztof Zdziarski 		blk_type = FIELD_PREP(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK, *type);
130266b0663SKrzysztof Zdziarski 		blk_byte = FIELD_PREP(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, *data);
131266b0663SKrzysztof Zdziarski 		max_data = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX;
132266b0663SKrzysztof Zdziarski 	} else if (*type <= ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX) {
133266b0663SKrzysztof Zdziarski 		msg_type = ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ;
134266b0663SKrzysztof Zdziarski 		blk_type = FIELD_PREP(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK,
135266b0663SKrzysztof Zdziarski 				      *type - ADF_VF2PF_SMALL_BLOCK_TYPE_MAX);
136266b0663SKrzysztof Zdziarski 		blk_byte = FIELD_PREP(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK, *data);
137266b0663SKrzysztof Zdziarski 		max_data = ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX;
138266b0663SKrzysztof Zdziarski 	} else if (*type <= ADF_VF2PF_LARGE_BLOCK_TYPE_MAX) {
139266b0663SKrzysztof Zdziarski 		msg_type = ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ;
140266b0663SKrzysztof Zdziarski 		blk_type = FIELD_PREP(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK,
141266b0663SKrzysztof Zdziarski 				      *type - ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX);
142266b0663SKrzysztof Zdziarski 		blk_byte = FIELD_PREP(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK, *data);
143266b0663SKrzysztof Zdziarski 		max_data = ADF_VF2PF_LARGE_BLOCK_BYTE_MAX;
144266b0663SKrzysztof Zdziarski 	} else {
145266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
146266b0663SKrzysztof Zdziarski 			      "Invalid message type %u\n",
147266b0663SKrzysztof Zdziarski 			      *type);
148266b0663SKrzysztof Zdziarski 		return -EINVAL;
149266b0663SKrzysztof Zdziarski 	}
150266b0663SKrzysztof Zdziarski 
151266b0663SKrzysztof Zdziarski 	/* Sanity check */
152266b0663SKrzysztof Zdziarski 	if (*data > max_data) {
153266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
154266b0663SKrzysztof Zdziarski 			      "Invalid byte %s %u for message type %u\n",
155266b0663SKrzysztof Zdziarski 			      crc ? "count" : "index",
156266b0663SKrzysztof Zdziarski 			      *data,
157266b0663SKrzysztof Zdziarski 			      *type);
158266b0663SKrzysztof Zdziarski 		return -EINVAL;
159266b0663SKrzysztof Zdziarski 	}
160266b0663SKrzysztof Zdziarski 
161266b0663SKrzysztof Zdziarski 	/* Build the block message */
162266b0663SKrzysztof Zdziarski 	req.type = msg_type;
163266b0663SKrzysztof Zdziarski 	req.data =
164266b0663SKrzysztof Zdziarski 	    blk_type | blk_byte | FIELD_PREP(ADF_VF2PF_BLOCK_CRC_REQ_MASK, crc);
165266b0663SKrzysztof Zdziarski 
166266b0663SKrzysztof Zdziarski 	err = adf_send_vf2pf_req(accel_dev, req, &resp);
167266b0663SKrzysztof Zdziarski 	if (err)
168266b0663SKrzysztof Zdziarski 		return err;
169266b0663SKrzysztof Zdziarski 
170266b0663SKrzysztof Zdziarski 	*type = FIELD_GET(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, resp.data);
171266b0663SKrzysztof Zdziarski 	*data = FIELD_GET(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, resp.data);
172266b0663SKrzysztof Zdziarski 
173266b0663SKrzysztof Zdziarski 	return 0;
174266b0663SKrzysztof Zdziarski }
175266b0663SKrzysztof Zdziarski 
176266b0663SKrzysztof Zdziarski static int
adf_vf2pf_blkmsg_get_byte(struct adf_accel_dev * accel_dev,u8 type,u8 index,u8 * data)177266b0663SKrzysztof Zdziarski adf_vf2pf_blkmsg_get_byte(struct adf_accel_dev *accel_dev,
178266b0663SKrzysztof Zdziarski 			  u8 type,
179266b0663SKrzysztof Zdziarski 			  u8 index,
180266b0663SKrzysztof Zdziarski 			  u8 *data)
181266b0663SKrzysztof Zdziarski {
182266b0663SKrzysztof Zdziarski 	int ret;
183266b0663SKrzysztof Zdziarski 
184266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_blkmsg_data_req(accel_dev, false, &type, &index);
185266b0663SKrzysztof Zdziarski 	if (ret < 0)
186266b0663SKrzysztof Zdziarski 		return ret;
187266b0663SKrzysztof Zdziarski 
188266b0663SKrzysztof Zdziarski 	if (unlikely(type != ADF_PF2VF_BLKMSG_RESP_TYPE_DATA)) {
189266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
190266b0663SKrzysztof Zdziarski 			      "Unexpected BLKMSG response type %u, byte 0x%x\n",
191266b0663SKrzysztof Zdziarski 			      type,
192266b0663SKrzysztof Zdziarski 			      index);
193266b0663SKrzysztof Zdziarski 		return -EFAULT;
194266b0663SKrzysztof Zdziarski 	}
195266b0663SKrzysztof Zdziarski 
196266b0663SKrzysztof Zdziarski 	*data = index;
197266b0663SKrzysztof Zdziarski 	return 0;
198266b0663SKrzysztof Zdziarski }
199266b0663SKrzysztof Zdziarski 
200266b0663SKrzysztof Zdziarski static int
adf_vf2pf_blkmsg_get_crc(struct adf_accel_dev * accel_dev,u8 type,u8 bytes,u8 * crc)201266b0663SKrzysztof Zdziarski adf_vf2pf_blkmsg_get_crc(struct adf_accel_dev *accel_dev,
202266b0663SKrzysztof Zdziarski 			 u8 type,
203266b0663SKrzysztof Zdziarski 			 u8 bytes,
204266b0663SKrzysztof Zdziarski 			 u8 *crc)
205266b0663SKrzysztof Zdziarski {
206266b0663SKrzysztof Zdziarski 	int ret;
207266b0663SKrzysztof Zdziarski 
208266b0663SKrzysztof Zdziarski 	/* The count of bytes refers to a length, however shift it to a 0-based
209266b0663SKrzysztof Zdziarski 	 * count to avoid overflows. Thus, a request for 0 bytes is technically
210266b0663SKrzysztof Zdziarski 	 * valid.
211266b0663SKrzysztof Zdziarski 	 */
212266b0663SKrzysztof Zdziarski 	--bytes;
213266b0663SKrzysztof Zdziarski 
214266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_blkmsg_data_req(accel_dev, true, &type, &bytes);
215266b0663SKrzysztof Zdziarski 	if (ret < 0)
216266b0663SKrzysztof Zdziarski 		return ret;
217266b0663SKrzysztof Zdziarski 
218266b0663SKrzysztof Zdziarski 	if (unlikely(type != ADF_PF2VF_BLKMSG_RESP_TYPE_CRC)) {
219266b0663SKrzysztof Zdziarski 		device_printf(
220266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
221266b0663SKrzysztof Zdziarski 		    "Unexpected CRC BLKMSG response type %u, crc 0x%x\n",
222266b0663SKrzysztof Zdziarski 		    type,
223266b0663SKrzysztof Zdziarski 		    bytes);
224266b0663SKrzysztof Zdziarski 		return -EFAULT;
225266b0663SKrzysztof Zdziarski 	}
226266b0663SKrzysztof Zdziarski 
227266b0663SKrzysztof Zdziarski 	*crc = bytes;
228266b0663SKrzysztof Zdziarski 	return 0;
229266b0663SKrzysztof Zdziarski }
230266b0663SKrzysztof Zdziarski 
231266b0663SKrzysztof Zdziarski /**
232266b0663SKrzysztof Zdziarski  * adf_send_vf2pf_blkmsg_req() - retrieve block message
233266b0663SKrzysztof Zdziarski  * @accel_dev:	Pointer to acceleration VF device.
234266b0663SKrzysztof Zdziarski  * @type:	The block message type, see adf_pfvf_msg.h for allowed values
235266b0663SKrzysztof Zdziarski  * @buffer:	input buffer where to place the received data
236266b0663SKrzysztof Zdziarski  * @buffer_len:	buffer length as input, the amount of written bytes on output
237266b0663SKrzysztof Zdziarski  *
238266b0663SKrzysztof Zdziarski  * Request a message of type 'type' over the block message transport.
239266b0663SKrzysztof Zdziarski  * This function will send the required amount block message requests and
240266b0663SKrzysztof Zdziarski  * return the overall content back to the caller through the provided buffer.
241266b0663SKrzysztof Zdziarski  * The buffer should be large enough to contain the requested message type,
242266b0663SKrzysztof Zdziarski  * otherwise the response will be truncated.
243266b0663SKrzysztof Zdziarski  *
244266b0663SKrzysztof Zdziarski  * Return: 0 on success, error code otherwise.
245266b0663SKrzysztof Zdziarski  */
246266b0663SKrzysztof Zdziarski int
adf_send_vf2pf_blkmsg_req(struct adf_accel_dev * accel_dev,u8 type,u8 * buffer,unsigned int * buffer_len)247266b0663SKrzysztof Zdziarski adf_send_vf2pf_blkmsg_req(struct adf_accel_dev *accel_dev,
248266b0663SKrzysztof Zdziarski 			  u8 type,
249266b0663SKrzysztof Zdziarski 			  u8 *buffer,
250266b0663SKrzysztof Zdziarski 			  unsigned int *buffer_len)
251266b0663SKrzysztof Zdziarski {
252266b0663SKrzysztof Zdziarski 	unsigned int index;
253266b0663SKrzysztof Zdziarski 	unsigned int msg_len;
254266b0663SKrzysztof Zdziarski 	int ret;
255266b0663SKrzysztof Zdziarski 	u8 remote_crc;
256266b0663SKrzysztof Zdziarski 	u8 local_crc;
257266b0663SKrzysztof Zdziarski 
258266b0663SKrzysztof Zdziarski 	if (unlikely(type > ADF_VF2PF_LARGE_BLOCK_TYPE_MAX)) {
259266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
260266b0663SKrzysztof Zdziarski 			      "Invalid block message type %d\n",
261266b0663SKrzysztof Zdziarski 			      type);
262266b0663SKrzysztof Zdziarski 		return -EINVAL;
263266b0663SKrzysztof Zdziarski 	}
264266b0663SKrzysztof Zdziarski 
265266b0663SKrzysztof Zdziarski 	if (unlikely(*buffer_len < ADF_PFVF_BLKMSG_HEADER_SIZE)) {
266266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
267266b0663SKrzysztof Zdziarski 			      "Buffer size too small for a block message\n");
268266b0663SKrzysztof Zdziarski 		return -EINVAL;
269266b0663SKrzysztof Zdziarski 	}
270266b0663SKrzysztof Zdziarski 
271266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
272266b0663SKrzysztof Zdziarski 					type,
273266b0663SKrzysztof Zdziarski 					ADF_PFVF_BLKMSG_VER_BYTE,
274266b0663SKrzysztof Zdziarski 					&buffer[ADF_PFVF_BLKMSG_VER_BYTE]);
275266b0663SKrzysztof Zdziarski 	if (unlikely(ret))
276266b0663SKrzysztof Zdziarski 		return ret;
277266b0663SKrzysztof Zdziarski 
278266b0663SKrzysztof Zdziarski 	if (unlikely(!buffer[ADF_PFVF_BLKMSG_VER_BYTE])) {
279266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
280266b0663SKrzysztof Zdziarski 			      "Invalid version 0 received for block request %u",
281266b0663SKrzysztof Zdziarski 			      type);
282266b0663SKrzysztof Zdziarski 		return -EFAULT;
283266b0663SKrzysztof Zdziarski 	}
284266b0663SKrzysztof Zdziarski 
285266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
286266b0663SKrzysztof Zdziarski 					type,
287266b0663SKrzysztof Zdziarski 					ADF_PFVF_BLKMSG_LEN_BYTE,
288266b0663SKrzysztof Zdziarski 					&buffer[ADF_PFVF_BLKMSG_LEN_BYTE]);
289266b0663SKrzysztof Zdziarski 	if (unlikely(ret))
290266b0663SKrzysztof Zdziarski 		return ret;
291266b0663SKrzysztof Zdziarski 
292266b0663SKrzysztof Zdziarski 	if (unlikely(!buffer[ADF_PFVF_BLKMSG_LEN_BYTE])) {
293266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
294266b0663SKrzysztof Zdziarski 			      "Invalid size 0 received for block request %u",
295266b0663SKrzysztof Zdziarski 			      type);
296266b0663SKrzysztof Zdziarski 		return -EFAULT;
297266b0663SKrzysztof Zdziarski 	}
298266b0663SKrzysztof Zdziarski 
299266b0663SKrzysztof Zdziarski 	/* We need to pick the minimum since there is no way to request a
300266b0663SKrzysztof Zdziarski 	 * specific version. As a consequence any scenario is possible:
301266b0663SKrzysztof Zdziarski 	 * - PF has a newer (longer) version which doesn't fit in the buffer
302266b0663SKrzysztof Zdziarski 	 * - VF expects a newer (longer) version, so we must not ask for
303266b0663SKrzysztof Zdziarski 	 *   bytes in excess
304266b0663SKrzysztof Zdziarski 	 * - PF and VF share the same version, no problem
305266b0663SKrzysztof Zdziarski 	 */
306266b0663SKrzysztof Zdziarski 	msg_len =
307266b0663SKrzysztof Zdziarski 	    ADF_PFVF_BLKMSG_HEADER_SIZE + buffer[ADF_PFVF_BLKMSG_LEN_BYTE];
308266b0663SKrzysztof Zdziarski 	msg_len = min(*buffer_len, msg_len);
309266b0663SKrzysztof Zdziarski 
310266b0663SKrzysztof Zdziarski 	/* Get the payload */
311266b0663SKrzysztof Zdziarski 	for (index = ADF_PFVF_BLKMSG_HEADER_SIZE; index < msg_len; index++) {
312266b0663SKrzysztof Zdziarski 		ret = adf_vf2pf_blkmsg_get_byte(accel_dev,
313266b0663SKrzysztof Zdziarski 						type,
314266b0663SKrzysztof Zdziarski 						index,
315266b0663SKrzysztof Zdziarski 						&buffer[index]);
316266b0663SKrzysztof Zdziarski 		if (unlikely(ret))
317266b0663SKrzysztof Zdziarski 			return ret;
318266b0663SKrzysztof Zdziarski 	}
319266b0663SKrzysztof Zdziarski 
320266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_blkmsg_get_crc(accel_dev, type, msg_len, &remote_crc);
321266b0663SKrzysztof Zdziarski 	if (unlikely(ret))
322266b0663SKrzysztof Zdziarski 		return ret;
323266b0663SKrzysztof Zdziarski 
324266b0663SKrzysztof Zdziarski 	local_crc = adf_pfvf_calc_blkmsg_crc(buffer, msg_len);
325266b0663SKrzysztof Zdziarski 	if (unlikely(local_crc != remote_crc)) {
326266b0663SKrzysztof Zdziarski 		device_printf(
327266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
328266b0663SKrzysztof Zdziarski 		    "CRC error on msg type %d. Local %02X, remote %02X\n",
329266b0663SKrzysztof Zdziarski 		    type,
330266b0663SKrzysztof Zdziarski 		    local_crc,
331266b0663SKrzysztof Zdziarski 		    remote_crc);
332266b0663SKrzysztof Zdziarski 		return -EIO;
333266b0663SKrzysztof Zdziarski 	}
334266b0663SKrzysztof Zdziarski 
335266b0663SKrzysztof Zdziarski 	*buffer_len = msg_len;
336266b0663SKrzysztof Zdziarski 	return 0;
337266b0663SKrzysztof Zdziarski }
338266b0663SKrzysztof Zdziarski 
339266b0663SKrzysztof Zdziarski static bool
adf_handle_pf2vf_msg(struct adf_accel_dev * accel_dev,struct pfvf_message msg)340266b0663SKrzysztof Zdziarski adf_handle_pf2vf_msg(struct adf_accel_dev *accel_dev, struct pfvf_message msg)
341266b0663SKrzysztof Zdziarski {
342266b0663SKrzysztof Zdziarski 	switch (msg.type) {
343266b0663SKrzysztof Zdziarski 	case ADF_PF2VF_MSGTYPE_RESTARTING:
344266b0663SKrzysztof Zdziarski 		adf_pf2vf_handle_pf_restarting(accel_dev);
345266b0663SKrzysztof Zdziarski 		return false;
346266b0663SKrzysztof Zdziarski 	case ADF_PF2VF_MSGTYPE_RP_RESET_RESP:
347266b0663SKrzysztof Zdziarski 		adf_pf2vf_handle_pf_rp_reset(accel_dev, msg);
348266b0663SKrzysztof Zdziarski 		return true;
349266b0663SKrzysztof Zdziarski 	case ADF_PF2VF_MSGTYPE_VERSION_RESP:
350266b0663SKrzysztof Zdziarski 	case ADF_PF2VF_MSGTYPE_BLKMSG_RESP:
351266b0663SKrzysztof Zdziarski 		accel_dev->u1.vf.response = msg;
352266b0663SKrzysztof Zdziarski 		complete(&accel_dev->u1.vf.msg_received);
353266b0663SKrzysztof Zdziarski 		return true;
354266b0663SKrzysztof Zdziarski 	default:
355266b0663SKrzysztof Zdziarski 		device_printf(
356266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
357266b0663SKrzysztof Zdziarski 		    "Unknown message from PF (type 0x%.4x, data: 0x%.4x)\n",
358266b0663SKrzysztof Zdziarski 		    msg.type,
359266b0663SKrzysztof Zdziarski 		    msg.data);
360266b0663SKrzysztof Zdziarski 	}
361266b0663SKrzysztof Zdziarski 
362266b0663SKrzysztof Zdziarski 	return false;
363266b0663SKrzysztof Zdziarski }
364266b0663SKrzysztof Zdziarski 
365266b0663SKrzysztof Zdziarski bool
adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev * accel_dev)366266b0663SKrzysztof Zdziarski adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev *accel_dev)
367266b0663SKrzysztof Zdziarski {
368266b0663SKrzysztof Zdziarski 	struct pfvf_message msg;
369266b0663SKrzysztof Zdziarski 
370266b0663SKrzysztof Zdziarski 	msg = adf_recv_pf2vf_msg(accel_dev);
371266b0663SKrzysztof Zdziarski 	if (msg.type) /* Invalid or no message */
372266b0663SKrzysztof Zdziarski 		return adf_handle_pf2vf_msg(accel_dev, msg);
373266b0663SKrzysztof Zdziarski 
374266b0663SKrzysztof Zdziarski 	/* No replies for PF->VF messages at present */
375266b0663SKrzysztof Zdziarski 
376266b0663SKrzysztof Zdziarski 	return true;
377266b0663SKrzysztof Zdziarski }
378266b0663SKrzysztof Zdziarski 
379266b0663SKrzysztof Zdziarski /**
380266b0663SKrzysztof Zdziarski  * adf_enable_vf2pf_comms() - Function enables communication from vf to pf
381266b0663SKrzysztof Zdziarski  *
382266b0663SKrzysztof Zdziarski  * @accel_dev:	Pointer to acceleration device virtual function.
383266b0663SKrzysztof Zdziarski  *
384266b0663SKrzysztof Zdziarski  * Return: 0 on success, error code otherwise.
385266b0663SKrzysztof Zdziarski  */
386266b0663SKrzysztof Zdziarski int
adf_enable_vf2pf_comms(struct adf_accel_dev * accel_dev)387266b0663SKrzysztof Zdziarski adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
388266b0663SKrzysztof Zdziarski {
389266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
390266b0663SKrzysztof Zdziarski 	int ret;
391266b0663SKrzysztof Zdziarski 
392*22cf89c9SPiotr Kasierski 	/* init workqueue for VF */
393*22cf89c9SPiotr Kasierski 	ret = adf_init_vf_wq();
394*22cf89c9SPiotr Kasierski 	if (ret)
395*22cf89c9SPiotr Kasierski 		return ret;
396*22cf89c9SPiotr Kasierski 
397266b0663SKrzysztof Zdziarski 	hw_data->enable_pf2vf_interrupt(accel_dev);
398266b0663SKrzysztof Zdziarski 
399266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_request_version(accel_dev);
400266b0663SKrzysztof Zdziarski 	if (ret)
401266b0663SKrzysztof Zdziarski 		return ret;
402266b0663SKrzysztof Zdziarski 
403266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_get_capabilities(accel_dev);
404266b0663SKrzysztof Zdziarski 	if (ret)
405266b0663SKrzysztof Zdziarski 		return ret;
406266b0663SKrzysztof Zdziarski 
407266b0663SKrzysztof Zdziarski 	ret = adf_vf2pf_get_ring_to_svc(accel_dev);
408266b0663SKrzysztof Zdziarski 	return ret;
409266b0663SKrzysztof Zdziarski }
410