]> Git Repo - J-linux.git/blob - drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / crypto / intel / qat / qat_common / adf_pfvf_pf_proto.c
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/spinlock.h>
5 #include <linux/types.h>
6 #include "adf_accel_devices.h"
7 #include "adf_common_drv.h"
8 #include "adf_pfvf_msg.h"
9 #include "adf_pfvf_pf_msg.h"
10 #include "adf_pfvf_pf_proto.h"
11 #include "adf_pfvf_utils.h"
12
13 typedef u8 (*pf2vf_blkmsg_data_getter_fn)(u8 const *blkmsg, u8 byte);
14
15 static const adf_pf2vf_blkmsg_provider pf2vf_blkmsg_providers[] = {
16         NULL,                             /* no message type defined for value 0 */
17         NULL,                             /* no message type defined for value 1 */
18         adf_pf_capabilities_msg_provider, /* ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY */
19         adf_pf_ring_to_svc_msg_provider,  /* ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP */
20 };
21
22 /**
23  * adf_send_pf2vf_msg() - send PF to VF message
24  * @accel_dev:  Pointer to acceleration device
25  * @vf_nr:      VF number to which the message will be sent
26  * @msg:        Message to send
27  *
28  * This function allows the PF to send a message to a specific VF.
29  *
30  * Return: 0 on success, error code otherwise.
31  */
32 int adf_send_pf2vf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr, struct pfvf_message msg)
33 {
34         struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
35         u32 pfvf_offset = pfvf_ops->get_pf2vf_offset(vf_nr);
36
37         return pfvf_ops->send_msg(accel_dev, msg, pfvf_offset,
38                                   &accel_dev->pf.vf_info[vf_nr].pf2vf_lock);
39 }
40
41 /**
42  * adf_recv_vf2pf_msg() - receive a VF to PF message
43  * @accel_dev:  Pointer to acceleration device
44  * @vf_nr:      Number of the VF from where the message will be received
45  *
46  * This function allows the PF to receive a message from a specific VF.
47  *
48  * Return: a valid message on success, zero otherwise.
49  */
50 static struct pfvf_message adf_recv_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr)
51 {
52         struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr];
53         struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
54         u32 pfvf_offset = pfvf_ops->get_vf2pf_offset(vf_nr);
55
56         return pfvf_ops->recv_msg(accel_dev, pfvf_offset, vf_info->vf_compat_ver);
57 }
58
59 static adf_pf2vf_blkmsg_provider get_blkmsg_response_provider(u8 type)
60 {
61         if (type >= ARRAY_SIZE(pf2vf_blkmsg_providers))
62                 return NULL;
63
64         return pf2vf_blkmsg_providers[type];
65 }
66
67 /* Byte pf2vf_blkmsg_data_getter_fn callback */
68 static u8 adf_pf2vf_blkmsg_get_byte(u8 const *blkmsg, u8 index)
69 {
70         return blkmsg[index];
71 }
72
73 /* CRC pf2vf_blkmsg_data_getter_fn callback */
74 static u8 adf_pf2vf_blkmsg_get_crc(u8 const *blkmsg, u8 count)
75 {
76         /* count is 0-based, turn it into a length */
77         return adf_pfvf_calc_blkmsg_crc(blkmsg, count + 1);
78 }
79
80 static int adf_pf2vf_blkmsg_get_data(struct adf_accel_vf_info *vf_info,
81                                      u8 type, u8 byte, u8 max_size, u8 *data,
82                                      pf2vf_blkmsg_data_getter_fn data_getter)
83 {
84         u8 blkmsg[ADF_PFVF_BLKMSG_MSG_MAX_SIZE] = { 0 };
85         struct adf_accel_dev *accel_dev = vf_info->accel_dev;
86         adf_pf2vf_blkmsg_provider provider;
87         u8 msg_size;
88
89         provider = get_blkmsg_response_provider(type);
90
91         if (unlikely(!provider)) {
92                 pr_err("QAT: No registered provider for message %d\n", type);
93                 *data = ADF_PF2VF_INVALID_BLOCK_TYPE;
94                 return -EINVAL;
95         }
96
97         if (unlikely((*provider)(accel_dev, blkmsg, vf_info->vf_compat_ver))) {
98                 pr_err("QAT: unknown error from provider for message %d\n", type);
99                 *data = ADF_PF2VF_UNSPECIFIED_ERROR;
100                 return -EINVAL;
101         }
102
103         msg_size = ADF_PFVF_BLKMSG_HEADER_SIZE + blkmsg[ADF_PFVF_BLKMSG_LEN_BYTE];
104
105         if (unlikely(msg_size >= max_size)) {
106                 pr_err("QAT: Invalid size %d provided for message type %d\n",
107                        msg_size, type);
108                 *data = ADF_PF2VF_PAYLOAD_TRUNCATED;
109                 return -EINVAL;
110         }
111
112         if (unlikely(byte >= msg_size)) {
113                 pr_err("QAT: Out-of-bound byte number %d (msg size %d)\n",
114                        byte, msg_size);
115                 *data = ADF_PF2VF_INVALID_BYTE_NUM_REQ;
116                 return -EINVAL;
117         }
118
119         *data = data_getter(blkmsg, byte);
120         return 0;
121 }
122
123 static struct pfvf_message handle_blkmsg_req(struct adf_accel_vf_info *vf_info,
124                                              struct pfvf_message req)
125 {
126         u8 resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR;
127         struct pfvf_message resp = { 0 };
128         u8 resp_data = 0;
129         u8 blk_type;
130         u8 blk_byte;
131         u8 byte_max;
132
133         switch (req.type) {
134         case ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ:
135                 blk_type = FIELD_GET(ADF_VF2PF_LARGE_BLOCK_TYPE_MASK, req.data)
136                            + ADF_VF2PF_MEDIUM_BLOCK_TYPE_MAX + 1;
137                 blk_byte = FIELD_GET(ADF_VF2PF_LARGE_BLOCK_BYTE_MASK, req.data);
138                 byte_max = ADF_VF2PF_LARGE_BLOCK_BYTE_MAX;
139                 break;
140         case ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ:
141                 blk_type = FIELD_GET(ADF_VF2PF_MEDIUM_BLOCK_TYPE_MASK, req.data)
142                            + ADF_VF2PF_SMALL_BLOCK_TYPE_MAX + 1;
143                 blk_byte = FIELD_GET(ADF_VF2PF_MEDIUM_BLOCK_BYTE_MASK, req.data);
144                 byte_max = ADF_VF2PF_MEDIUM_BLOCK_BYTE_MAX;
145                 break;
146         case ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ:
147                 blk_type = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_TYPE_MASK, req.data);
148                 blk_byte = FIELD_GET(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, req.data);
149                 byte_max = ADF_VF2PF_SMALL_BLOCK_BYTE_MAX;
150                 break;
151         }
152
153         /* Is this a request for CRC or data? */
154         if (FIELD_GET(ADF_VF2PF_BLOCK_CRC_REQ_MASK, req.data)) {
155                 dev_dbg(&GET_DEV(vf_info->accel_dev),
156                         "BlockMsg of type %d for CRC over %d bytes received from VF%d\n",
157                         blk_type, blk_byte + 1, vf_info->vf_nr);
158
159                 if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte,
160                                                byte_max, &resp_data,
161                                                adf_pf2vf_blkmsg_get_crc))
162                         resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_CRC;
163         } else {
164                 dev_dbg(&GET_DEV(vf_info->accel_dev),
165                         "BlockMsg of type %d for data byte %d received from VF%d\n",
166                         blk_type, blk_byte, vf_info->vf_nr);
167
168                 if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte,
169                                                byte_max, &resp_data,
170                                                adf_pf2vf_blkmsg_get_byte))
171                         resp_type = ADF_PF2VF_BLKMSG_RESP_TYPE_DATA;
172         }
173
174         resp.type = ADF_PF2VF_MSGTYPE_BLKMSG_RESP;
175         resp.data = FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, resp_type) |
176                     FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, resp_data);
177
178         return resp;
179 }
180
181 static struct pfvf_message handle_rp_reset_req(struct adf_accel_dev *accel_dev, u8 vf_nr,
182                                                struct pfvf_message req)
183 {
184         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
185         struct pfvf_message resp = {
186                 .type = ADF_PF2VF_MSGTYPE_RP_RESET_RESP,
187                 .data = RPRESET_SUCCESS
188         };
189         u32 bank_number;
190         u32 rsvd_field;
191
192         bank_number = FIELD_GET(ADF_VF2PF_RNG_RESET_RP_MASK, req.data);
193         rsvd_field = FIELD_GET(ADF_VF2PF_RNG_RESET_RSVD_MASK, req.data);
194
195         dev_dbg(&GET_DEV(accel_dev),
196                 "Ring Pair Reset Message received from VF%d for bank 0x%x\n",
197                 vf_nr, bank_number);
198
199         if (!hw_data->ring_pair_reset || rsvd_field) {
200                 dev_dbg(&GET_DEV(accel_dev),
201                         "Ring Pair Reset for VF%d is not supported\n", vf_nr);
202                 resp.data = RPRESET_NOT_SUPPORTED;
203                 goto out;
204         }
205
206         if (bank_number >= hw_data->num_banks_per_vf) {
207                 dev_err(&GET_DEV(accel_dev),
208                         "Invalid bank number (0x%x) from VF%d for Ring Reset\n",
209                         bank_number, vf_nr);
210                 resp.data = RPRESET_INVAL_BANK;
211                 goto out;
212         }
213
214         /* Convert the VF provided value to PF bank number */
215         bank_number = vf_nr * hw_data->num_banks_per_vf + bank_number;
216         if (hw_data->ring_pair_reset(accel_dev, bank_number)) {
217                 dev_dbg(&GET_DEV(accel_dev),
218                         "Ring pair reset for VF%d failure\n", vf_nr);
219                 resp.data = RPRESET_TIMEOUT;
220                 goto out;
221         }
222
223         dev_dbg(&GET_DEV(accel_dev),
224                 "Ring pair reset for VF%d successfully\n", vf_nr);
225
226 out:
227         return resp;
228 }
229
230 static int adf_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr,
231                                 struct pfvf_message msg, struct pfvf_message *resp)
232 {
233         struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr];
234
235         switch (msg.type) {
236         case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ:
237                 {
238                 u8 vf_compat_ver = msg.data;
239                 u8 compat;
240
241                 dev_dbg(&GET_DEV(accel_dev),
242                         "VersionRequest received from VF%d (vers %d) to PF (vers %d)\n",
243                         vf_nr, vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION);
244
245                 compat = adf_vf_compat_checker(vf_compat_ver);
246                 vf_info->vf_compat_ver = vf_compat_ver;
247
248                 resp->type = ADF_PF2VF_MSGTYPE_VERSION_RESP;
249                 resp->data = FIELD_PREP(ADF_PF2VF_VERSION_RESP_VERS_MASK,
250                                         ADF_PFVF_COMPAT_THIS_VERSION) |
251                              FIELD_PREP(ADF_PF2VF_VERSION_RESP_RESULT_MASK, compat);
252                 }
253                 break;
254         case ADF_VF2PF_MSGTYPE_VERSION_REQ:
255                 {
256                 u8 compat;
257
258                 dev_dbg(&GET_DEV(accel_dev),
259                         "Legacy VersionRequest received from VF%d to PF (vers 1.1)\n",
260                         vf_nr);
261
262                 /* legacy driver, VF compat_ver is 0 */
263                 vf_info->vf_compat_ver = 0;
264
265                 /* PF always newer than legacy VF */
266                 compat = ADF_PF2VF_VF_COMPATIBLE;
267
268                 /* Set legacy major and minor version to the latest, 1.1 */
269                 resp->type = ADF_PF2VF_MSGTYPE_VERSION_RESP;
270                 resp->data = FIELD_PREP(ADF_PF2VF_VERSION_RESP_VERS_MASK, 0x11) |
271                              FIELD_PREP(ADF_PF2VF_VERSION_RESP_RESULT_MASK, compat);
272                 }
273                 break;
274         case ADF_VF2PF_MSGTYPE_INIT:
275                 {
276                 dev_dbg(&GET_DEV(accel_dev),
277                         "Init message received from VF%d\n", vf_nr);
278                 vf_info->init = true;
279                 }
280                 break;
281         case ADF_VF2PF_MSGTYPE_SHUTDOWN:
282                 {
283                 dev_dbg(&GET_DEV(accel_dev),
284                         "Shutdown message received from VF%d\n", vf_nr);
285                 vf_info->init = false;
286                 }
287                 break;
288         case ADF_VF2PF_MSGTYPE_RESTARTING_COMPLETE:
289                 {
290                 dev_dbg(&GET_DEV(accel_dev),
291                         "Restarting Complete received from VF%d\n", vf_nr);
292                 vf_info->restarting = false;
293                 vf_info->init = false;
294                 }
295                 break;
296         case ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ:
297         case ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ:
298         case ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ:
299                 *resp = handle_blkmsg_req(vf_info, msg);
300                 break;
301         case ADF_VF2PF_MSGTYPE_RP_RESET:
302                 *resp = handle_rp_reset_req(accel_dev, vf_nr, msg);
303                 break;
304         default:
305                 dev_dbg(&GET_DEV(accel_dev),
306                         "Unknown message from VF%d (type 0x%.4x, data: 0x%.4x)\n",
307                         vf_nr, msg.type, msg.data);
308                 return -ENOMSG;
309         }
310
311         return 0;
312 }
313
314 bool adf_recv_and_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr)
315 {
316         struct pfvf_message req;
317         struct pfvf_message resp = {0};
318
319         req = adf_recv_vf2pf_msg(accel_dev, vf_nr);
320         if (!req.type)  /* Legacy or no message */
321                 return true;
322
323         if (adf_handle_vf2pf_msg(accel_dev, vf_nr, req, &resp))
324                 return false;
325
326         if (resp.type && adf_send_pf2vf_msg(accel_dev, vf_nr, resp))
327                 dev_err(&GET_DEV(accel_dev),
328                         "Failed to send response to VF%d\n", vf_nr);
329
330         return true;
331 }
332
333 /**
334  * adf_enable_pf2vf_comms() - Function enables communication from pf to vf
335  *
336  * @accel_dev: Pointer to acceleration device virtual function.
337  *
338  * This function carries out the necessary steps to setup and start the PFVF
339  * communication channel, if any.
340  *
341  * Return: 0 on success, error code otherwise.
342  */
343 int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev)
344 {
345         adf_pfvf_crc_init();
346         spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);
347
348         return 0;
349 }
350 EXPORT_SYMBOL_GPL(adf_enable_pf2vf_comms);
This page took 0.04841 seconds and 4 git commands to generate.