These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / crypto / qat / qat_dh895xccvf / adf_isr.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) 2014 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) 2014 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/kernel.h>
48 #include <linux/init.h>
49 #include <linux/types.h>
50 #include <linux/pci.h>
51 #include <linux/slab.h>
52 #include <linux/errno.h>
53 #include <linux/interrupt.h>
54 #include <adf_accel_devices.h>
55 #include <adf_common_drv.h>
56 #include <adf_cfg.h>
57 #include <adf_cfg_strings.h>
58 #include <adf_cfg_common.h>
59 #include <adf_transport_access_macros.h>
60 #include <adf_transport_internal.h>
61 #include <adf_pf2vf_msg.h>
62 #include "adf_drv.h"
63 #include "adf_dh895xccvf_hw_data.h"
64
65 static int adf_enable_msi(struct adf_accel_dev *accel_dev)
66 {
67         struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
68         int stat = pci_enable_msi(pci_dev_info->pci_dev);
69
70         if (stat) {
71                 dev_err(&GET_DEV(accel_dev),
72                         "Failed to enable MSI interrupts\n");
73                 return stat;
74         }
75
76         accel_dev->vf.irq_name = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
77         if (!accel_dev->vf.irq_name)
78                 return -ENOMEM;
79
80         return stat;
81 }
82
83 static void adf_disable_msi(struct adf_accel_dev *accel_dev)
84 {
85         struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
86
87         kfree(accel_dev->vf.irq_name);
88         pci_disable_msi(pdev);
89 }
90
91 static void adf_pf2vf_bh_handler(void *data)
92 {
93         struct adf_accel_dev *accel_dev = data;
94         void __iomem *pmisc_bar_addr =
95                 (&GET_BARS(accel_dev)[ADF_DH895XCCIOV_PMISC_BAR])->virt_addr;
96         u32 msg;
97
98         /* Read the message from PF */
99         msg = ADF_CSR_RD(pmisc_bar_addr, ADF_DH895XCCIOV_PF2VF_OFFSET);
100
101         if (!(msg & ADF_PF2VF_MSGORIGIN_SYSTEM))
102                 /* Ignore legacy non-system (non-kernel) PF2VF messages */
103                 goto err;
104
105         switch ((msg & ADF_PF2VF_MSGTYPE_MASK) >> ADF_PF2VF_MSGTYPE_SHIFT) {
106         case ADF_PF2VF_MSGTYPE_RESTARTING:
107                 dev_dbg(&GET_DEV(accel_dev),
108                         "Restarting msg received from PF 0x%x\n", msg);
109                 adf_dev_stop(accel_dev);
110                 break;
111         case ADF_PF2VF_MSGTYPE_VERSION_RESP:
112                 dev_dbg(&GET_DEV(accel_dev),
113                         "Version resp received from PF 0x%x\n", msg);
114                 accel_dev->vf.pf_version =
115                         (msg & ADF_PF2VF_VERSION_RESP_VERS_MASK) >>
116                         ADF_PF2VF_VERSION_RESP_VERS_SHIFT;
117                 accel_dev->vf.compatible =
118                         (msg & ADF_PF2VF_VERSION_RESP_RESULT_MASK) >>
119                         ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
120                 complete(&accel_dev->vf.iov_msg_completion);
121                 break;
122         default:
123                 goto err;
124         }
125
126         /* To ack, clear the PF2VFINT bit */
127         msg &= ~ADF_DH895XCC_PF2VF_PF2VFINT;
128         ADF_CSR_WR(pmisc_bar_addr, ADF_DH895XCCIOV_PF2VF_OFFSET, msg);
129
130         /* Re-enable PF2VF interrupts */
131         adf_enable_pf2vf_interrupts(accel_dev);
132         return;
133 err:
134         dev_err(&GET_DEV(accel_dev),
135                 "Unknown message from PF (0x%x); leaving PF2VF ints disabled\n",
136                 msg);
137 }
138
139 static int adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev)
140 {
141         tasklet_init(&accel_dev->vf.pf2vf_bh_tasklet,
142                      (void *)adf_pf2vf_bh_handler, (unsigned long)accel_dev);
143
144         mutex_init(&accel_dev->vf.vf2pf_lock);
145         return 0;
146 }
147
148 static void adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev)
149 {
150         tasklet_disable(&accel_dev->vf.pf2vf_bh_tasklet);
151         tasklet_kill(&accel_dev->vf.pf2vf_bh_tasklet);
152         mutex_destroy(&accel_dev->vf.vf2pf_lock);
153 }
154
155 static irqreturn_t adf_isr(int irq, void *privdata)
156 {
157         struct adf_accel_dev *accel_dev = privdata;
158         void __iomem *pmisc_bar_addr =
159                 (&GET_BARS(accel_dev)[ADF_DH895XCCIOV_PMISC_BAR])->virt_addr;
160         u32 v_int;
161
162         /* Read VF INT source CSR to determine the source of VF interrupt */
163         v_int = ADF_CSR_RD(pmisc_bar_addr, ADF_DH895XCCIOV_VINTSOU_OFFSET);
164
165         /* Check for PF2VF interrupt */
166         if (v_int & ADF_DH895XCC_VINTSOU_PF2VF) {
167                 /* Disable PF to VF interrupt */
168                 adf_disable_pf2vf_interrupts(accel_dev);
169
170                 /* Schedule tasklet to handle interrupt BH */
171                 tasklet_hi_schedule(&accel_dev->vf.pf2vf_bh_tasklet);
172                 return IRQ_HANDLED;
173         }
174
175         /* Check bundle interrupt */
176         if (v_int & ADF_DH895XCC_VINTSOU_BUN) {
177                 struct adf_etr_data *etr_data = accel_dev->transport;
178                 struct adf_etr_bank_data *bank = &etr_data->banks[0];
179
180                 /* Disable Flag and Coalesce Ring Interrupts */
181                 WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number,
182                                            0);
183                 tasklet_hi_schedule(&bank->resp_handler);
184                 return IRQ_HANDLED;
185         }
186
187         return IRQ_NONE;
188 }
189
190 static int adf_request_msi_irq(struct adf_accel_dev *accel_dev)
191 {
192         struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
193         unsigned int cpu;
194         int ret;
195
196         snprintf(accel_dev->vf.irq_name, ADF_MAX_MSIX_VECTOR_NAME,
197                  "qat_%02x:%02d.%02d", pdev->bus->number, PCI_SLOT(pdev->devfn),
198                  PCI_FUNC(pdev->devfn));
199         ret = request_irq(pdev->irq, adf_isr, 0, accel_dev->vf.irq_name,
200                           (void *)accel_dev);
201         if (ret) {
202                 dev_err(&GET_DEV(accel_dev), "failed to enable irq for %s\n",
203                         accel_dev->vf.irq_name);
204                 return ret;
205         }
206         cpu = accel_dev->accel_id % num_online_cpus();
207         irq_set_affinity_hint(pdev->irq, get_cpu_mask(cpu));
208
209         return ret;
210 }
211
212 static int adf_setup_bh(struct adf_accel_dev *accel_dev)
213 {
214         struct adf_etr_data *priv_data = accel_dev->transport;
215
216         tasklet_init(&priv_data->banks[0].resp_handler, adf_response_handler,
217                      (unsigned long)priv_data->banks);
218         return 0;
219 }
220
221 static void adf_cleanup_bh(struct adf_accel_dev *accel_dev)
222 {
223         struct adf_etr_data *priv_data = accel_dev->transport;
224
225         tasklet_disable(&priv_data->banks[0].resp_handler);
226         tasklet_kill(&priv_data->banks[0].resp_handler);
227 }
228
229 void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev)
230 {
231         struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
232
233         irq_set_affinity_hint(pdev->irq, NULL);
234         free_irq(pdev->irq, (void *)accel_dev);
235         adf_cleanup_bh(accel_dev);
236         adf_cleanup_pf2vf_bh(accel_dev);
237         adf_disable_msi(accel_dev);
238 }
239
240 int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
241 {
242         if (adf_enable_msi(accel_dev))
243                 goto err_out;
244
245         if (adf_setup_pf2vf_bh(accel_dev))
246                 goto err_out;
247
248         if (adf_setup_bh(accel_dev))
249                 goto err_out;
250
251         if (adf_request_msi_irq(accel_dev))
252                 goto err_out;
253
254         return 0;
255 err_out:
256         adf_vf_isr_resource_free(accel_dev);
257         return -EFAULT;
258 }