]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/crypto/qat/qat_common/adf_sriov.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide
[karo-tx-linux.git] / drivers / crypto / qat / qat_common / adf_sriov.c
1 /*
2   This file is provided under a dual BSD/GPLv2 license.  When using or
3   redistributing this file, you may do so under either license.
4
5   GPL LICENSE SUMMARY
6   Copyright(c) 2015 Intel Corporation.
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of version 2 of the GNU General Public License as
9   published by the Free Software Foundation.
10
11   This program is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15
16   Contact Information:
17   qat-linux@intel.com
18
19   BSD LICENSE
20   Copyright(c) 2015 Intel Corporation.
21   Redistribution and use in source and binary forms, with or without
22   modification, are permitted provided that the following conditions
23   are met:
24
25     * Redistributions of source code must retain the above copyright
26       notice, this list of conditions and the following disclaimer.
27     * Redistributions in binary form must reproduce the above copyright
28       notice, this list of conditions and the following disclaimer in
29       the documentation and/or other materials provided with the
30       distribution.
31     * Neither the name of Intel Corporation nor the names of its
32       contributors may be used to endorse or promote products derived
33       from this software without specific prior written permission.
34
35   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 */
47 #include <linux/workqueue.h>
48 #include <linux/pci.h>
49 #include <linux/device.h>
50 #include <linux/iommu.h>
51 #include "adf_common_drv.h"
52 #include "adf_cfg.h"
53 #include "adf_pf2vf_msg.h"
54
55 static struct workqueue_struct *pf2vf_resp_wq;
56
57 #define ME2FUNCTION_MAP_A_OFFSET        (0x3A400 + 0x190)
58 #define ME2FUNCTION_MAP_A_NUM_REGS      96
59
60 #define ME2FUNCTION_MAP_B_OFFSET        (0x3A400 + 0x310)
61 #define ME2FUNCTION_MAP_B_NUM_REGS      12
62
63 #define ME2FUNCTION_MAP_REG_SIZE        4
64 #define ME2FUNCTION_MAP_VALID           BIT(7)
65
66 #define READ_CSR_ME2FUNCTION_MAP_A(pmisc_bar_addr, index)               \
67         ADF_CSR_RD(pmisc_bar_addr, ME2FUNCTION_MAP_A_OFFSET +           \
68                    ME2FUNCTION_MAP_REG_SIZE * index)
69
70 #define WRITE_CSR_ME2FUNCTION_MAP_A(pmisc_bar_addr, index, value)       \
71         ADF_CSR_WR(pmisc_bar_addr, ME2FUNCTION_MAP_A_OFFSET +           \
72                    ME2FUNCTION_MAP_REG_SIZE * index, value)
73
74 #define READ_CSR_ME2FUNCTION_MAP_B(pmisc_bar_addr, index)               \
75         ADF_CSR_RD(pmisc_bar_addr, ME2FUNCTION_MAP_B_OFFSET +           \
76                    ME2FUNCTION_MAP_REG_SIZE * index)
77
78 #define WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_bar_addr, index, value)       \
79         ADF_CSR_WR(pmisc_bar_addr, ME2FUNCTION_MAP_B_OFFSET +           \
80                    ME2FUNCTION_MAP_REG_SIZE * index, value)
81
82 struct adf_pf2vf_resp {
83         struct work_struct pf2vf_resp_work;
84         struct adf_accel_vf_info *vf_info;
85 };
86
87 static void adf_iov_send_resp(struct work_struct *work)
88 {
89         struct adf_pf2vf_resp *pf2vf_resp =
90                 container_of(work, struct adf_pf2vf_resp, pf2vf_resp_work);
91
92         adf_vf2pf_req_hndl(pf2vf_resp->vf_info);
93         kfree(pf2vf_resp);
94 }
95
96 static void adf_vf2pf_bh_handler(void *data)
97 {
98         struct adf_accel_vf_info *vf_info = (struct adf_accel_vf_info *)data;
99         struct adf_pf2vf_resp *pf2vf_resp;
100
101         pf2vf_resp = kzalloc(sizeof(*pf2vf_resp), GFP_ATOMIC);
102         if (!pf2vf_resp)
103                 return;
104
105         pf2vf_resp->vf_info = vf_info;
106         INIT_WORK(&pf2vf_resp->pf2vf_resp_work, adf_iov_send_resp);
107         queue_work(pf2vf_resp_wq, &pf2vf_resp->pf2vf_resp_work);
108 }
109
110 static int adf_enable_sriov(struct adf_accel_dev *accel_dev)
111 {
112         struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
113         int totalvfs = pci_sriov_get_totalvfs(pdev);
114         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
115         struct adf_bar *pmisc =
116                         &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
117         void __iomem *pmisc_addr = pmisc->virt_addr;
118         struct adf_accel_vf_info *vf_info;
119         int i;
120         u32 reg;
121
122         /* Workqueue for PF2VF responses */
123         pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq");
124         if (!pf2vf_resp_wq)
125                 return -ENOMEM;
126
127         for (i = 0, vf_info = accel_dev->pf.vf_info; i < totalvfs;
128              i++, vf_info++) {
129                 /* This ptr will be populated when VFs will be created */
130                 vf_info->accel_dev = accel_dev;
131                 vf_info->vf_nr = i;
132
133                 tasklet_init(&vf_info->vf2pf_bh_tasklet,
134                              (void *)adf_vf2pf_bh_handler,
135                              (unsigned long)vf_info);
136                 mutex_init(&vf_info->pf2vf_lock);
137                 ratelimit_state_init(&vf_info->vf2pf_ratelimit,
138                                      DEFAULT_RATELIMIT_INTERVAL,
139                                      DEFAULT_RATELIMIT_BURST);
140         }
141
142         /* Set Valid bits in ME Thread to PCIe Function Mapping Group A */
143         for (i = 0; i < ME2FUNCTION_MAP_A_NUM_REGS; i++) {
144                 reg = READ_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i);
145                 reg |= ME2FUNCTION_MAP_VALID;
146                 WRITE_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i, reg);
147         }
148
149         /* Set Valid bits in ME Thread to PCIe Function Mapping Group B */
150         for (i = 0; i < ME2FUNCTION_MAP_B_NUM_REGS; i++) {
151                 reg = READ_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i);
152                 reg |= ME2FUNCTION_MAP_VALID;
153                 WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i, reg);
154         }
155
156         /* Enable VF to PF interrupts for all VFs */
157         adf_enable_vf2pf_interrupts(accel_dev, GENMASK_ULL(totalvfs - 1, 0));
158
159         /*
160          * Due to the hardware design, when SR-IOV and the ring arbiter
161          * are enabled all the VFs supported in hardware must be enabled in
162          * order for all the hardware resources (i.e. bundles) to be usable.
163          * When SR-IOV is enabled, each of the VFs will own one bundle.
164          */
165         return pci_enable_sriov(pdev, totalvfs);
166 }
167
168 /**
169  * adf_disable_sriov() - Disable SRIOV for the device
170  * @pdev:  Pointer to pci device.
171  *
172  * Function disables SRIOV for the pci device.
173  *
174  * Return: 0 on success, error code otherwise.
175  */
176 void adf_disable_sriov(struct adf_accel_dev *accel_dev)
177 {
178         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
179         struct adf_bar *pmisc =
180                         &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
181         void __iomem *pmisc_addr = pmisc->virt_addr;
182         int totalvfs = pci_sriov_get_totalvfs(accel_to_pci_dev(accel_dev));
183         struct adf_accel_vf_info *vf;
184         u32 reg;
185         int i;
186
187         if (!accel_dev->pf.vf_info)
188                 return;
189
190         adf_pf2vf_notify_restarting(accel_dev);
191
192         pci_disable_sriov(accel_to_pci_dev(accel_dev));
193
194         /* Disable VF to PF interrupts */
195         adf_disable_vf2pf_interrupts(accel_dev, 0xFFFFFFFF);
196
197         /* Clear Valid bits in ME Thread to PCIe Function Mapping Group A */
198         for (i = 0; i < ME2FUNCTION_MAP_A_NUM_REGS; i++) {
199                 reg = READ_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i);
200                 reg &= ~ME2FUNCTION_MAP_VALID;
201                 WRITE_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i, reg);
202         }
203
204         /* Clear Valid bits in ME Thread to PCIe Function Mapping Group B */
205         for (i = 0; i < ME2FUNCTION_MAP_B_NUM_REGS; i++) {
206                 reg = READ_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i);
207                 reg &= ~ME2FUNCTION_MAP_VALID;
208                 WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i, reg);
209         }
210
211         for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) {
212                 tasklet_disable(&vf->vf2pf_bh_tasklet);
213                 tasklet_kill(&vf->vf2pf_bh_tasklet);
214                 mutex_destroy(&vf->pf2vf_lock);
215         }
216
217         kfree(accel_dev->pf.vf_info);
218         accel_dev->pf.vf_info = NULL;
219
220         if (pf2vf_resp_wq) {
221                 destroy_workqueue(pf2vf_resp_wq);
222                 pf2vf_resp_wq = NULL;
223         }
224 }
225 EXPORT_SYMBOL_GPL(adf_disable_sriov);
226
227 /**
228  * adf_sriov_configure() - Enable SRIOV for the device
229  * @pdev:  Pointer to pci device.
230  *
231  * Function enables SRIOV for the pci device.
232  *
233  * Return: 0 on success, error code otherwise.
234  */
235 int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
236 {
237         struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
238         int totalvfs = pci_sriov_get_totalvfs(pdev);
239         unsigned long val;
240         int ret;
241
242         if (!accel_dev) {
243                 dev_err(&pdev->dev, "Failed to find accel_dev\n");
244                 return -EFAULT;
245         }
246
247         if (!iommu_present(&pci_bus_type))
248                 dev_warn(&pdev->dev, "IOMMU should be enabled for SR-IOV to work correctly\n");
249
250         if (accel_dev->pf.vf_info) {
251                 dev_info(&pdev->dev, "Already enabled for this device\n");
252                 return -EINVAL;
253         }
254
255         if (adf_dev_started(accel_dev)) {
256                 if (adf_devmgr_in_reset(accel_dev) ||
257                     adf_dev_in_use(accel_dev)) {
258                         dev_err(&GET_DEV(accel_dev), "Device busy\n");
259                         return -EBUSY;
260                 }
261
262                 if (adf_dev_stop(accel_dev)) {
263                         dev_err(&GET_DEV(accel_dev),
264                                 "Failed to stop qat_dev%d\n",
265                                 accel_dev->accel_id);
266                         return -EFAULT;
267                 }
268
269                 adf_dev_shutdown(accel_dev);
270         }
271
272         if (adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC))
273                 return -EFAULT;
274         val = 0;
275         if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
276                                         ADF_NUM_CY, (void *)&val, ADF_DEC))
277                 return -EFAULT;
278
279         set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
280
281         /* Allocate memory for VF info structs */
282         accel_dev->pf.vf_info = kcalloc(totalvfs,
283                                         sizeof(struct adf_accel_vf_info),
284                                         GFP_KERNEL);
285         if (!accel_dev->pf.vf_info)
286                 return -ENOMEM;
287
288         if (adf_dev_init(accel_dev)) {
289                 dev_err(&GET_DEV(accel_dev), "Failed to init qat_dev%d\n",
290                         accel_dev->accel_id);
291                 return -EFAULT;
292         }
293
294         if (adf_dev_start(accel_dev)) {
295                 dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
296                         accel_dev->accel_id);
297                 return -EFAULT;
298         }
299
300         ret = adf_enable_sriov(accel_dev);
301         if (ret)
302                 return ret;
303
304         return numvfs;
305 }
306 EXPORT_SYMBOL_GPL(adf_sriov_configure);