GNU Linux-libre 5.16.19-gnu
[releases.git] / drivers / crypto / qat / qat_common / adf_pf2vf_msg.c
1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2 /* Copyright(c) 2015 - 2020 Intel Corporation */
3 #include <linux/delay.h>
4 #include "adf_accel_devices.h"
5 #include "adf_common_drv.h"
6 #include "adf_pf2vf_msg.h"
7
8 #define ADF_PFVF_MSG_COLLISION_DETECT_DELAY     10
9 #define ADF_PFVF_MSG_ACK_DELAY                  2
10 #define ADF_PFVF_MSG_ACK_MAX_RETRY              100
11 #define ADF_PFVF_MSG_RETRY_DELAY                5
12 #define ADF_PFVF_MSG_MAX_RETRIES                3
13 #define ADF_PFVF_MSG_RESP_TIMEOUT       (ADF_PFVF_MSG_ACK_DELAY * \
14                                          ADF_PFVF_MSG_ACK_MAX_RETRY + \
15                                          ADF_PFVF_MSG_COLLISION_DETECT_DELAY)
16
17 void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
18 {
19         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
20         u32 misc_bar_id = hw_data->get_misc_bar_id(hw_data);
21         struct adf_bar *pmisc = &GET_BARS(accel_dev)[misc_bar_id];
22         void __iomem *pmisc_addr = pmisc->virt_addr;
23         unsigned long flags;
24
25         spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags);
26         hw_data->enable_vf2pf_interrupts(pmisc_addr, vf_mask);
27         spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
28 }
29
30 void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
31 {
32         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
33         u32 misc_bar_id = hw_data->get_misc_bar_id(hw_data);
34         struct adf_bar *pmisc = &GET_BARS(accel_dev)[misc_bar_id];
35         void __iomem *pmisc_addr = pmisc->virt_addr;
36         unsigned long flags;
37
38         spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags);
39         hw_data->disable_vf2pf_interrupts(pmisc_addr, vf_mask);
40         spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
41 }
42
43 void adf_disable_vf2pf_interrupts_irq(struct adf_accel_dev *accel_dev,
44                                       u32 vf_mask)
45 {
46         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
47         u32 misc_bar_id = hw_data->get_misc_bar_id(hw_data);
48         struct adf_bar *pmisc = &GET_BARS(accel_dev)[misc_bar_id];
49         void __iomem *pmisc_addr = pmisc->virt_addr;
50
51         spin_lock(&accel_dev->pf.vf2pf_ints_lock);
52         hw_data->disable_vf2pf_interrupts(pmisc_addr, vf_mask);
53         spin_unlock(&accel_dev->pf.vf2pf_ints_lock);
54 }
55
56 static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr)
57 {
58         struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
59         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
60         void __iomem *pmisc_bar_addr =
61                 pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;
62         u32 val, pf2vf_offset, count = 0;
63         u32 local_in_use_mask, local_in_use_pattern;
64         u32 remote_in_use_mask, remote_in_use_pattern;
65         struct mutex *lock;     /* lock preventing concurrent acces of CSR */
66         u32 int_bit;
67         int ret = 0;
68
69         if (accel_dev->is_vf) {
70                 pf2vf_offset = hw_data->get_pf2vf_offset(0);
71                 lock = &accel_dev->vf.vf2pf_lock;
72                 local_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
73                 local_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
74                 remote_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
75                 remote_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
76                 int_bit = ADF_VF2PF_INT;
77         } else {
78                 pf2vf_offset = hw_data->get_pf2vf_offset(vf_nr);
79                 lock = &accel_dev->pf.vf_info[vf_nr].pf2vf_lock;
80                 local_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
81                 local_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
82                 remote_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
83                 remote_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
84                 int_bit = ADF_PF2VF_INT;
85         }
86
87         mutex_lock(lock);
88
89         /* Check if the PFVF CSR is in use by remote function */
90         val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
91         if ((val & remote_in_use_mask) == remote_in_use_pattern) {
92                 dev_dbg(&GET_DEV(accel_dev),
93                         "PFVF CSR in use by remote function\n");
94                 ret = -EBUSY;
95                 goto out;
96         }
97
98         msg &= ~local_in_use_mask;
99         msg |= local_in_use_pattern;
100
101         /* Attempt to get ownership of the PFVF CSR */
102         ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg | int_bit);
103
104         /* Wait for confirmation from remote func it received the message */
105         do {
106                 msleep(ADF_PFVF_MSG_ACK_DELAY);
107                 val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
108         } while ((val & int_bit) && (count++ < ADF_PFVF_MSG_ACK_MAX_RETRY));
109
110         if (val & int_bit) {
111                 dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");
112                 val &= ~int_bit;
113                 ret = -EIO;
114         }
115
116         if (val != msg) {
117                 dev_dbg(&GET_DEV(accel_dev),
118                         "Collision - PFVF CSR overwritten by remote function\n");
119                 ret = -EIO;
120                 goto out;
121         }
122
123         /* Finished with the PFVF CSR; relinquish it and leave msg in CSR */
124         ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, val & ~local_in_use_mask);
125 out:
126         mutex_unlock(lock);
127         return ret;
128 }
129
130 /**
131  * adf_iov_putmsg() - send PFVF message
132  * @accel_dev:  Pointer to acceleration device.
133  * @msg:        Message to send
134  * @vf_nr:      VF number to which the message will be sent if on PF, ignored
135  *              otherwise
136  *
137  * Function sends a message through the PFVF channel
138  *
139  * Return: 0 on success, error code otherwise.
140  */
141 static int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr)
142 {
143         u32 count = 0;
144         int ret;
145
146         do {
147                 ret = __adf_iov_putmsg(accel_dev, msg, vf_nr);
148                 if (ret)
149                         msleep(ADF_PFVF_MSG_RETRY_DELAY);
150         } while (ret && (count++ < ADF_PFVF_MSG_MAX_RETRIES));
151
152         return ret;
153 }
154
155 /**
156  * adf_send_pf2vf_msg() - send PF to VF message
157  * @accel_dev:  Pointer to acceleration device
158  * @vf_nr:      VF number to which the message will be sent
159  * @msg:        Message to send
160  *
161  * This function allows the PF to send a message to a specific VF.
162  *
163  * Return: 0 on success, error code otherwise.
164  */
165 static int adf_send_pf2vf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr, u32 msg)
166 {
167         return adf_iov_putmsg(accel_dev, msg, vf_nr);
168 }
169
170 /**
171  * adf_send_vf2pf_msg() - send VF to PF message
172  * @accel_dev:  Pointer to acceleration device
173  * @msg:        Message to send
174  *
175  * This function allows the VF to send a message to the PF.
176  *
177  * Return: 0 on success, error code otherwise.
178  */
179 int adf_send_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 msg)
180 {
181         return adf_iov_putmsg(accel_dev, msg, 0);
182 }
183
184 /**
185  * adf_send_vf2pf_req() - send VF2PF request message
186  * @accel_dev:  Pointer to acceleration device.
187  * @msg:        Request message to send
188  *
189  * This function sends a message that requires a response from the VF to the PF
190  * and waits for a reply.
191  *
192  * Return: 0 on success, error code otherwise.
193  */
194 static int adf_send_vf2pf_req(struct adf_accel_dev *accel_dev, u32 msg)
195 {
196         unsigned long timeout = msecs_to_jiffies(ADF_PFVF_MSG_RESP_TIMEOUT);
197         int ret;
198
199         reinit_completion(&accel_dev->vf.iov_msg_completion);
200
201         /* Send request from VF to PF */
202         ret = adf_send_vf2pf_msg(accel_dev, msg);
203         if (ret) {
204                 dev_err(&GET_DEV(accel_dev),
205                         "Failed to send request msg to PF\n");
206                 return ret;
207         }
208
209         /* Wait for response */
210         if (!wait_for_completion_timeout(&accel_dev->vf.iov_msg_completion,
211                                          timeout)) {
212                 dev_err(&GET_DEV(accel_dev),
213                         "PFVF request/response message timeout expired\n");
214                 return -EIO;
215         }
216
217         return 0;
218 }
219
220 void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info)
221 {
222         struct adf_accel_dev *accel_dev = vf_info->accel_dev;
223         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
224         int bar_id = hw_data->get_misc_bar_id(hw_data);
225         struct adf_bar *pmisc = &GET_BARS(accel_dev)[bar_id];
226         void __iomem *pmisc_addr = pmisc->virt_addr;
227         u32 msg, resp = 0, vf_nr = vf_info->vf_nr;
228
229         /* Read message from the VF */
230         msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr));
231         if (!(msg & ADF_VF2PF_INT)) {
232                 dev_info(&GET_DEV(accel_dev),
233                          "Spurious VF2PF interrupt, msg %X. Ignored\n", msg);
234                 goto out;
235         }
236
237         /* To ACK, clear the VF2PFINT bit */
238         msg &= ~ADF_VF2PF_INT;
239         ADF_CSR_WR(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr), msg);
240
241         if (!(msg & ADF_VF2PF_MSGORIGIN_SYSTEM))
242                 /* Ignore legacy non-system (non-kernel) VF2PF messages */
243                 goto err;
244
245         switch ((msg & ADF_VF2PF_MSGTYPE_MASK) >> ADF_VF2PF_MSGTYPE_SHIFT) {
246         case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ:
247                 {
248                 u8 vf_compat_ver = msg >> ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
249
250                 resp = (ADF_PF2VF_MSGORIGIN_SYSTEM |
251                          (ADF_PF2VF_MSGTYPE_VERSION_RESP <<
252                           ADF_PF2VF_MSGTYPE_SHIFT) |
253                          (ADF_PFVF_COMPAT_THIS_VERSION <<
254                           ADF_PF2VF_VERSION_RESP_VERS_SHIFT));
255
256                 dev_dbg(&GET_DEV(accel_dev),
257                         "Compatibility Version Request from VF%d vers=%u\n",
258                         vf_nr + 1, vf_compat_ver);
259
260                 if (vf_compat_ver < hw_data->min_iov_compat_ver) {
261                         dev_err(&GET_DEV(accel_dev),
262                                 "VF (vers %d) incompatible with PF (vers %d)\n",
263                                 vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION);
264                         resp |= ADF_PF2VF_VF_INCOMPATIBLE <<
265                                 ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
266                 } else if (vf_compat_ver > ADF_PFVF_COMPAT_THIS_VERSION) {
267                         dev_err(&GET_DEV(accel_dev),
268                                 "VF (vers %d) compat with PF (vers %d) unkn.\n",
269                                 vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION);
270                         resp |= ADF_PF2VF_VF_COMPAT_UNKNOWN <<
271                                 ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
272                 } else {
273                         dev_dbg(&GET_DEV(accel_dev),
274                                 "VF (vers %d) compatible with PF (vers %d)\n",
275                                 vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION);
276                         resp |= ADF_PF2VF_VF_COMPATIBLE <<
277                                 ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
278                 }
279                 }
280                 break;
281         case ADF_VF2PF_MSGTYPE_VERSION_REQ:
282                 dev_dbg(&GET_DEV(accel_dev),
283                         "Legacy VersionRequest received from VF%d 0x%x\n",
284                         vf_nr + 1, msg);
285                 resp = (ADF_PF2VF_MSGORIGIN_SYSTEM |
286                          (ADF_PF2VF_MSGTYPE_VERSION_RESP <<
287                           ADF_PF2VF_MSGTYPE_SHIFT) |
288                          (ADF_PFVF_COMPAT_THIS_VERSION <<
289                           ADF_PF2VF_VERSION_RESP_VERS_SHIFT));
290                 resp |= ADF_PF2VF_VF_COMPATIBLE <<
291                         ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
292                 /* Set legacy major and minor version num */
293                 resp |= 1 << ADF_PF2VF_MAJORVERSION_SHIFT |
294                         1 << ADF_PF2VF_MINORVERSION_SHIFT;
295                 break;
296         case ADF_VF2PF_MSGTYPE_INIT:
297                 {
298                 dev_dbg(&GET_DEV(accel_dev),
299                         "Init message received from VF%d 0x%x\n",
300                         vf_nr + 1, msg);
301                 vf_info->init = true;
302                 }
303                 break;
304         case ADF_VF2PF_MSGTYPE_SHUTDOWN:
305                 {
306                 dev_dbg(&GET_DEV(accel_dev),
307                         "Shutdown message received from VF%d 0x%x\n",
308                         vf_nr + 1, msg);
309                 vf_info->init = false;
310                 }
311                 break;
312         default:
313                 goto err;
314         }
315
316         if (resp && adf_send_pf2vf_msg(accel_dev, vf_nr, resp))
317                 dev_err(&GET_DEV(accel_dev), "Failed to send response to VF\n");
318
319 out:
320         /* re-enable interrupt on PF from this VF */
321         adf_enable_vf2pf_interrupts(accel_dev, (1 << vf_nr));
322
323         return;
324 err:
325         dev_dbg(&GET_DEV(accel_dev), "Unknown message from VF%d (0x%x);\n",
326                 vf_nr + 1, msg);
327 }
328
329 void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev)
330 {
331         struct adf_accel_vf_info *vf;
332         u32 msg = (ADF_PF2VF_MSGORIGIN_SYSTEM |
333                 (ADF_PF2VF_MSGTYPE_RESTARTING << ADF_PF2VF_MSGTYPE_SHIFT));
334         int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));
335
336         for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) {
337                 if (vf->init && adf_send_pf2vf_msg(accel_dev, i, msg))
338                         dev_err(&GET_DEV(accel_dev),
339                                 "Failed to send restarting msg to VF%d\n", i);
340         }
341 }
342
343 static int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev)
344 {
345         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
346         u32 msg = 0;
347         int ret;
348
349         msg = ADF_VF2PF_MSGORIGIN_SYSTEM;
350         msg |= ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ << ADF_VF2PF_MSGTYPE_SHIFT;
351         msg |= ADF_PFVF_COMPAT_THIS_VERSION << ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
352         BUILD_BUG_ON(ADF_PFVF_COMPAT_THIS_VERSION > 255);
353
354         ret = adf_send_vf2pf_req(accel_dev, msg);
355         if (ret) {
356                 dev_err(&GET_DEV(accel_dev),
357                         "Failed to send Compatibility Version Request.\n");
358                 return ret;
359         }
360
361         /* Response from PF received, check compatibility */
362         switch (accel_dev->vf.compatible) {
363         case ADF_PF2VF_VF_COMPATIBLE:
364                 break;
365         case ADF_PF2VF_VF_COMPAT_UNKNOWN:
366                 /* VF is newer than PF and decides whether it is compatible */
367                 if (accel_dev->vf.pf_version >= hw_data->min_iov_compat_ver) {
368                         accel_dev->vf.compatible = ADF_PF2VF_VF_COMPATIBLE;
369                         break;
370                 }
371                 fallthrough;
372         case ADF_PF2VF_VF_INCOMPATIBLE:
373                 dev_err(&GET_DEV(accel_dev),
374                         "PF (vers %d) and VF (vers %d) are not compatible\n",
375                         accel_dev->vf.pf_version,
376                         ADF_PFVF_COMPAT_THIS_VERSION);
377                 return -EINVAL;
378         default:
379                 dev_err(&GET_DEV(accel_dev),
380                         "Invalid response from PF; assume not compatible\n");
381                 return -EINVAL;
382         }
383         return ret;
384 }
385
386 /**
387  * adf_enable_vf2pf_comms() - Function enables communication from vf to pf
388  *
389  * @accel_dev: Pointer to acceleration device virtual function.
390  *
391  * Return: 0 on success, error code otherwise.
392  */
393 int adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
394 {
395         adf_enable_pf2vf_interrupts(accel_dev);
396         return adf_vf2pf_request_version(accel_dev);
397 }
398 EXPORT_SYMBOL_GPL(adf_enable_vf2pf_comms);
399
400 /**
401  * adf_enable_pf2vf_comms() - Function enables communication from pf to vf
402  *
403  * @accel_dev: Pointer to acceleration device virtual function.
404  *
405  * This function carries out the necessary steps to setup and start the PFVF
406  * communication channel, if any.
407  *
408  * Return: 0 on success, error code otherwise.
409  */
410 int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev)
411 {
412         spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);
413
414         return 0;
415 }
416 EXPORT_SYMBOL_GPL(adf_enable_pf2vf_comms);