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
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 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
adf_vf2pf_blkmsg_data_req(struct adf_accel_dev * accel_dev,bool crc,u8 * type,u8 * data)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
adf_vf2pf_blkmsg_get_byte(struct adf_accel_dev * accel_dev,u8 type,u8 index,u8 * data)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
adf_vf2pf_blkmsg_get_crc(struct adf_accel_dev * accel_dev,u8 type,u8 bytes,u8 * crc)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
adf_send_vf2pf_blkmsg_req(struct adf_accel_dev * accel_dev,u8 type,u8 * buffer,unsigned int * buffer_len)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
adf_handle_pf2vf_msg(struct adf_accel_dev * accel_dev,struct pfvf_message msg)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
adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev * accel_dev)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
adf_enable_vf2pf_comms(struct adf_accel_dev * accel_dev)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