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