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