xref: /openbmc/linux/drivers/crypto/intel/qat/qat_common/adf_isr.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1a4b16dadSTom Zanussi // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2a4b16dadSTom Zanussi /* Copyright(c) 2014 - 2020 Intel Corporation */
3a4b16dadSTom Zanussi #include <linux/kernel.h>
4a4b16dadSTom Zanussi #include <linux/init.h>
5a4b16dadSTom Zanussi #include <linux/types.h>
6a4b16dadSTom Zanussi #include <linux/pci.h>
7a4b16dadSTom Zanussi #include <linux/slab.h>
8a4b16dadSTom Zanussi #include <linux/errno.h>
9a4b16dadSTom Zanussi #include <linux/interrupt.h>
10a4b16dadSTom Zanussi #include "adf_accel_devices.h"
11a4b16dadSTom Zanussi #include "adf_common_drv.h"
12a4b16dadSTom Zanussi #include "adf_cfg.h"
13a4b16dadSTom Zanussi #include "adf_cfg_strings.h"
14a4b16dadSTom Zanussi #include "adf_cfg_common.h"
15a4b16dadSTom Zanussi #include "adf_transport_access_macros.h"
16a4b16dadSTom Zanussi #include "adf_transport_internal.h"
17a4b16dadSTom Zanussi 
18a4b16dadSTom Zanussi #define ADF_MAX_NUM_VFS	32
19a4b16dadSTom Zanussi static struct workqueue_struct *adf_misc_wq;
20a4b16dadSTom Zanussi 
adf_enable_msix(struct adf_accel_dev * accel_dev)21a4b16dadSTom Zanussi static int adf_enable_msix(struct adf_accel_dev *accel_dev)
22a4b16dadSTom Zanussi {
23a4b16dadSTom Zanussi 	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
24a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
25a4b16dadSTom Zanussi 	u32 msix_num_entries = hw_data->num_banks + 1;
26a4b16dadSTom Zanussi 	int ret;
27a4b16dadSTom Zanussi 
28a4b16dadSTom Zanussi 	if (hw_data->set_msix_rttable)
29a4b16dadSTom Zanussi 		hw_data->set_msix_rttable(accel_dev);
30a4b16dadSTom Zanussi 
31a4b16dadSTom Zanussi 	ret = pci_alloc_irq_vectors(pci_dev_info->pci_dev, msix_num_entries,
32a4b16dadSTom Zanussi 				    msix_num_entries, PCI_IRQ_MSIX);
33a4b16dadSTom Zanussi 	if (unlikely(ret < 0)) {
34a4b16dadSTom Zanussi 		dev_err(&GET_DEV(accel_dev),
35a4b16dadSTom Zanussi 			"Failed to allocate %d MSI-X vectors\n",
36a4b16dadSTom Zanussi 			msix_num_entries);
37a4b16dadSTom Zanussi 		return ret;
38a4b16dadSTom Zanussi 	}
39a4b16dadSTom Zanussi 	return 0;
40a4b16dadSTom Zanussi }
41a4b16dadSTom Zanussi 
adf_disable_msix(struct adf_accel_pci * pci_dev_info)42a4b16dadSTom Zanussi static void adf_disable_msix(struct adf_accel_pci *pci_dev_info)
43a4b16dadSTom Zanussi {
44a4b16dadSTom Zanussi 	pci_free_irq_vectors(pci_dev_info->pci_dev);
45a4b16dadSTom Zanussi }
46a4b16dadSTom Zanussi 
adf_msix_isr_bundle(int irq,void * bank_ptr)47a4b16dadSTom Zanussi static irqreturn_t adf_msix_isr_bundle(int irq, void *bank_ptr)
48a4b16dadSTom Zanussi {
49a4b16dadSTom Zanussi 	struct adf_etr_bank_data *bank = bank_ptr;
50a4b16dadSTom Zanussi 	struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(bank->accel_dev);
51a4b16dadSTom Zanussi 
52a4b16dadSTom Zanussi 	csr_ops->write_csr_int_flag_and_col(bank->csr_addr, bank->bank_number,
53a4b16dadSTom Zanussi 					    0);
54a4b16dadSTom Zanussi 	tasklet_hi_schedule(&bank->resp_handler);
55a4b16dadSTom Zanussi 	return IRQ_HANDLED;
56a4b16dadSTom Zanussi }
57a4b16dadSTom Zanussi 
58a4b16dadSTom Zanussi #ifdef CONFIG_PCI_IOV
adf_enable_vf2pf_interrupts(struct adf_accel_dev * accel_dev,u32 vf_mask)59a4b16dadSTom Zanussi void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
60a4b16dadSTom Zanussi {
61a4b16dadSTom Zanussi 	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
62a4b16dadSTom Zanussi 	unsigned long flags;
63a4b16dadSTom Zanussi 
64a4b16dadSTom Zanussi 	spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags);
65a4b16dadSTom Zanussi 	GET_PFVF_OPS(accel_dev)->enable_vf2pf_interrupts(pmisc_addr, vf_mask);
66a4b16dadSTom Zanussi 	spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
67a4b16dadSTom Zanussi }
68a4b16dadSTom Zanussi 
adf_disable_all_vf2pf_interrupts(struct adf_accel_dev * accel_dev)69a4b16dadSTom Zanussi void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev)
70a4b16dadSTom Zanussi {
71a4b16dadSTom Zanussi 	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
72a4b16dadSTom Zanussi 	unsigned long flags;
73a4b16dadSTom Zanussi 
74a4b16dadSTom Zanussi 	spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags);
75a4b16dadSTom Zanussi 	GET_PFVF_OPS(accel_dev)->disable_all_vf2pf_interrupts(pmisc_addr);
76a4b16dadSTom Zanussi 	spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
77a4b16dadSTom Zanussi }
78a4b16dadSTom Zanussi 
adf_disable_pending_vf2pf_interrupts(struct adf_accel_dev * accel_dev)79a4b16dadSTom Zanussi static u32 adf_disable_pending_vf2pf_interrupts(struct adf_accel_dev *accel_dev)
80a4b16dadSTom Zanussi {
81a4b16dadSTom Zanussi 	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
82a4b16dadSTom Zanussi 	u32 pending;
83a4b16dadSTom Zanussi 
84a4b16dadSTom Zanussi 	spin_lock(&accel_dev->pf.vf2pf_ints_lock);
85a4b16dadSTom Zanussi 	pending = GET_PFVF_OPS(accel_dev)->disable_pending_vf2pf_interrupts(pmisc_addr);
86a4b16dadSTom Zanussi 	spin_unlock(&accel_dev->pf.vf2pf_ints_lock);
87a4b16dadSTom Zanussi 
88a4b16dadSTom Zanussi 	return pending;
89a4b16dadSTom Zanussi }
90a4b16dadSTom Zanussi 
adf_handle_vf2pf_int(struct adf_accel_dev * accel_dev)91a4b16dadSTom Zanussi static bool adf_handle_vf2pf_int(struct adf_accel_dev *accel_dev)
92a4b16dadSTom Zanussi {
93a4b16dadSTom Zanussi 	bool irq_handled = false;
94a4b16dadSTom Zanussi 	unsigned long vf_mask;
95a4b16dadSTom Zanussi 
96a4b16dadSTom Zanussi 	/* Get the interrupt sources triggered by VFs, except for those already disabled */
97a4b16dadSTom Zanussi 	vf_mask = adf_disable_pending_vf2pf_interrupts(accel_dev);
98a4b16dadSTom Zanussi 	if (vf_mask) {
99a4b16dadSTom Zanussi 		struct adf_accel_vf_info *vf_info;
100a4b16dadSTom Zanussi 		int i;
101a4b16dadSTom Zanussi 
102a4b16dadSTom Zanussi 		/*
103a4b16dadSTom Zanussi 		 * Handle VF2PF interrupt unless the VF is malicious and
104a4b16dadSTom Zanussi 		 * is attempting to flood the host OS with VF2PF interrupts.
105a4b16dadSTom Zanussi 		 */
106a4b16dadSTom Zanussi 		for_each_set_bit(i, &vf_mask, ADF_MAX_NUM_VFS) {
107a4b16dadSTom Zanussi 			vf_info = accel_dev->pf.vf_info + i;
108a4b16dadSTom Zanussi 
109a4b16dadSTom Zanussi 			if (!__ratelimit(&vf_info->vf2pf_ratelimit)) {
110a4b16dadSTom Zanussi 				dev_info(&GET_DEV(accel_dev),
111a4b16dadSTom Zanussi 					 "Too many ints from VF%d\n",
112a4b16dadSTom Zanussi 					  vf_info->vf_nr);
113a4b16dadSTom Zanussi 				continue;
114a4b16dadSTom Zanussi 			}
115a4b16dadSTom Zanussi 
116a4b16dadSTom Zanussi 			adf_schedule_vf2pf_handler(vf_info);
117a4b16dadSTom Zanussi 			irq_handled = true;
118a4b16dadSTom Zanussi 		}
119a4b16dadSTom Zanussi 	}
120a4b16dadSTom Zanussi 	return irq_handled;
121a4b16dadSTom Zanussi }
122a4b16dadSTom Zanussi #endif /* CONFIG_PCI_IOV */
123a4b16dadSTom Zanussi 
adf_handle_pm_int(struct adf_accel_dev * accel_dev)124a4b16dadSTom Zanussi static bool adf_handle_pm_int(struct adf_accel_dev *accel_dev)
125a4b16dadSTom Zanussi {
126a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
127a4b16dadSTom Zanussi 
128a4b16dadSTom Zanussi 	if (hw_data->handle_pm_interrupt &&
129a4b16dadSTom Zanussi 	    hw_data->handle_pm_interrupt(accel_dev))
130a4b16dadSTom Zanussi 		return true;
131a4b16dadSTom Zanussi 
132a4b16dadSTom Zanussi 	return false;
133a4b16dadSTom Zanussi }
134a4b16dadSTom Zanussi 
adf_msix_isr_ae(int irq,void * dev_ptr)135a4b16dadSTom Zanussi static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
136a4b16dadSTom Zanussi {
137a4b16dadSTom Zanussi 	struct adf_accel_dev *accel_dev = dev_ptr;
138a4b16dadSTom Zanussi 
139a4b16dadSTom Zanussi #ifdef CONFIG_PCI_IOV
140a4b16dadSTom Zanussi 	/* If SR-IOV is enabled (vf_info is non-NULL), check for VF->PF ints */
141a4b16dadSTom Zanussi 	if (accel_dev->pf.vf_info && adf_handle_vf2pf_int(accel_dev))
142a4b16dadSTom Zanussi 		return IRQ_HANDLED;
143a4b16dadSTom Zanussi #endif /* CONFIG_PCI_IOV */
144a4b16dadSTom Zanussi 
145a4b16dadSTom Zanussi 	if (adf_handle_pm_int(accel_dev))
146a4b16dadSTom Zanussi 		return IRQ_HANDLED;
147a4b16dadSTom Zanussi 
148a4b16dadSTom Zanussi 	dev_dbg(&GET_DEV(accel_dev), "qat_dev%d spurious AE interrupt\n",
149a4b16dadSTom Zanussi 		accel_dev->accel_id);
150a4b16dadSTom Zanussi 
151a4b16dadSTom Zanussi 	return IRQ_NONE;
152a4b16dadSTom Zanussi }
153a4b16dadSTom Zanussi 
adf_free_irqs(struct adf_accel_dev * accel_dev)154a4b16dadSTom Zanussi static void adf_free_irqs(struct adf_accel_dev *accel_dev)
155a4b16dadSTom Zanussi {
156a4b16dadSTom Zanussi 	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
157a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
158a4b16dadSTom Zanussi 	struct adf_irq *irqs = pci_dev_info->msix_entries.irqs;
159a4b16dadSTom Zanussi 	struct adf_etr_data *etr_data = accel_dev->transport;
160a4b16dadSTom Zanussi 	int clust_irq = hw_data->num_banks;
161a4b16dadSTom Zanussi 	int irq, i = 0;
162a4b16dadSTom Zanussi 
163a4b16dadSTom Zanussi 	if (pci_dev_info->msix_entries.num_entries > 1) {
164a4b16dadSTom Zanussi 		for (i = 0; i < hw_data->num_banks; i++) {
165a4b16dadSTom Zanussi 			if (irqs[i].enabled) {
166a4b16dadSTom Zanussi 				irq = pci_irq_vector(pci_dev_info->pci_dev, i);
167a4b16dadSTom Zanussi 				irq_set_affinity_hint(irq, NULL);
168a4b16dadSTom Zanussi 				free_irq(irq, &etr_data->banks[i]);
169a4b16dadSTom Zanussi 			}
170a4b16dadSTom Zanussi 		}
171a4b16dadSTom Zanussi 	}
172a4b16dadSTom Zanussi 
173a4b16dadSTom Zanussi 	if (irqs[i].enabled) {
174a4b16dadSTom Zanussi 		irq = pci_irq_vector(pci_dev_info->pci_dev, clust_irq);
175a4b16dadSTom Zanussi 		free_irq(irq, accel_dev);
176a4b16dadSTom Zanussi 	}
177a4b16dadSTom Zanussi }
178a4b16dadSTom Zanussi 
adf_request_irqs(struct adf_accel_dev * accel_dev)179a4b16dadSTom Zanussi static int adf_request_irqs(struct adf_accel_dev *accel_dev)
180a4b16dadSTom Zanussi {
181a4b16dadSTom Zanussi 	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
182a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
183a4b16dadSTom Zanussi 	struct adf_irq *irqs = pci_dev_info->msix_entries.irqs;
184a4b16dadSTom Zanussi 	struct adf_etr_data *etr_data = accel_dev->transport;
185a4b16dadSTom Zanussi 	int clust_irq = hw_data->num_banks;
186a4b16dadSTom Zanussi 	int ret, irq, i = 0;
187a4b16dadSTom Zanussi 	char *name;
188a4b16dadSTom Zanussi 
189a4b16dadSTom Zanussi 	/* Request msix irq for all banks unless SR-IOV enabled */
190a4b16dadSTom Zanussi 	if (!accel_dev->pf.vf_info) {
191a4b16dadSTom Zanussi 		for (i = 0; i < hw_data->num_banks; i++) {
192a4b16dadSTom Zanussi 			struct adf_etr_bank_data *bank = &etr_data->banks[i];
193a4b16dadSTom Zanussi 			unsigned int cpu, cpus = num_online_cpus();
194a4b16dadSTom Zanussi 
195a4b16dadSTom Zanussi 			name = irqs[i].name;
196a4b16dadSTom Zanussi 			snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
197a4b16dadSTom Zanussi 				 "qat%d-bundle%d", accel_dev->accel_id, i);
198a4b16dadSTom Zanussi 			irq = pci_irq_vector(pci_dev_info->pci_dev, i);
199a4b16dadSTom Zanussi 			if (unlikely(irq < 0)) {
200a4b16dadSTom Zanussi 				dev_err(&GET_DEV(accel_dev),
201a4b16dadSTom Zanussi 					"Failed to get IRQ number of device vector %d - %s\n",
202a4b16dadSTom Zanussi 					i, name);
203a4b16dadSTom Zanussi 				ret = irq;
204a4b16dadSTom Zanussi 				goto err;
205a4b16dadSTom Zanussi 			}
206a4b16dadSTom Zanussi 			ret = request_irq(irq, adf_msix_isr_bundle, 0,
207a4b16dadSTom Zanussi 					  &name[0], bank);
208a4b16dadSTom Zanussi 			if (ret) {
209a4b16dadSTom Zanussi 				dev_err(&GET_DEV(accel_dev),
210a4b16dadSTom Zanussi 					"Failed to allocate IRQ %d for %s\n",
211a4b16dadSTom Zanussi 					irq, name);
212a4b16dadSTom Zanussi 				goto err;
213a4b16dadSTom Zanussi 			}
214a4b16dadSTom Zanussi 
215a4b16dadSTom Zanussi 			cpu = ((accel_dev->accel_id * hw_data->num_banks) +
216a4b16dadSTom Zanussi 			       i) % cpus;
217a4b16dadSTom Zanussi 			irq_set_affinity_hint(irq, get_cpu_mask(cpu));
218a4b16dadSTom Zanussi 			irqs[i].enabled = true;
219a4b16dadSTom Zanussi 		}
220a4b16dadSTom Zanussi 	}
221a4b16dadSTom Zanussi 
222a4b16dadSTom Zanussi 	/* Request msix irq for AE */
223a4b16dadSTom Zanussi 	name = irqs[i].name;
224a4b16dadSTom Zanussi 	snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
225a4b16dadSTom Zanussi 		 "qat%d-ae-cluster", accel_dev->accel_id);
226a4b16dadSTom Zanussi 	irq = pci_irq_vector(pci_dev_info->pci_dev, clust_irq);
227a4b16dadSTom Zanussi 	if (unlikely(irq < 0)) {
228a4b16dadSTom Zanussi 		dev_err(&GET_DEV(accel_dev),
229a4b16dadSTom Zanussi 			"Failed to get IRQ number of device vector %d - %s\n",
230a4b16dadSTom Zanussi 			i, name);
231a4b16dadSTom Zanussi 		ret = irq;
232a4b16dadSTom Zanussi 		goto err;
233a4b16dadSTom Zanussi 	}
234a4b16dadSTom Zanussi 	ret = request_irq(irq, adf_msix_isr_ae, 0, &name[0], accel_dev);
235a4b16dadSTom Zanussi 	if (ret) {
236a4b16dadSTom Zanussi 		dev_err(&GET_DEV(accel_dev),
237a4b16dadSTom Zanussi 			"Failed to allocate IRQ %d for %s\n", irq, name);
238a4b16dadSTom Zanussi 		goto err;
239a4b16dadSTom Zanussi 	}
240a4b16dadSTom Zanussi 	irqs[i].enabled = true;
241a4b16dadSTom Zanussi 	return ret;
242a4b16dadSTom Zanussi err:
243a4b16dadSTom Zanussi 	adf_free_irqs(accel_dev);
244a4b16dadSTom Zanussi 	return ret;
245a4b16dadSTom Zanussi }
246a4b16dadSTom Zanussi 
adf_isr_alloc_msix_vectors_data(struct adf_accel_dev * accel_dev)247a4b16dadSTom Zanussi static int adf_isr_alloc_msix_vectors_data(struct adf_accel_dev *accel_dev)
248a4b16dadSTom Zanussi {
249a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
250a4b16dadSTom Zanussi 	u32 msix_num_entries = 1;
251a4b16dadSTom Zanussi 	struct adf_irq *irqs;
252a4b16dadSTom Zanussi 
253a4b16dadSTom Zanussi 	/* If SR-IOV is disabled (vf_info is NULL), add entries for each bank */
254a4b16dadSTom Zanussi 	if (!accel_dev->pf.vf_info)
255a4b16dadSTom Zanussi 		msix_num_entries += hw_data->num_banks;
256a4b16dadSTom Zanussi 
257a4b16dadSTom Zanussi 	irqs = kzalloc_node(msix_num_entries * sizeof(*irqs),
258a4b16dadSTom Zanussi 			    GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev)));
259a4b16dadSTom Zanussi 	if (!irqs)
260a4b16dadSTom Zanussi 		return -ENOMEM;
261a4b16dadSTom Zanussi 
262a4b16dadSTom Zanussi 	accel_dev->accel_pci_dev.msix_entries.num_entries = msix_num_entries;
263a4b16dadSTom Zanussi 	accel_dev->accel_pci_dev.msix_entries.irqs = irqs;
264a4b16dadSTom Zanussi 	return 0;
265a4b16dadSTom Zanussi }
266a4b16dadSTom Zanussi 
adf_isr_free_msix_vectors_data(struct adf_accel_dev * accel_dev)267a4b16dadSTom Zanussi static void adf_isr_free_msix_vectors_data(struct adf_accel_dev *accel_dev)
268a4b16dadSTom Zanussi {
269a4b16dadSTom Zanussi 	kfree(accel_dev->accel_pci_dev.msix_entries.irqs);
270a4b16dadSTom Zanussi 	accel_dev->accel_pci_dev.msix_entries.irqs = NULL;
271a4b16dadSTom Zanussi }
272a4b16dadSTom Zanussi 
adf_setup_bh(struct adf_accel_dev * accel_dev)273a4b16dadSTom Zanussi static int adf_setup_bh(struct adf_accel_dev *accel_dev)
274a4b16dadSTom Zanussi {
275a4b16dadSTom Zanussi 	struct adf_etr_data *priv_data = accel_dev->transport;
276a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
277a4b16dadSTom Zanussi 	int i;
278a4b16dadSTom Zanussi 
279a4b16dadSTom Zanussi 	for (i = 0; i < hw_data->num_banks; i++)
280a4b16dadSTom Zanussi 		tasklet_init(&priv_data->banks[i].resp_handler,
281a4b16dadSTom Zanussi 			     adf_response_handler,
282a4b16dadSTom Zanussi 			     (unsigned long)&priv_data->banks[i]);
283a4b16dadSTom Zanussi 	return 0;
284a4b16dadSTom Zanussi }
285a4b16dadSTom Zanussi 
adf_cleanup_bh(struct adf_accel_dev * accel_dev)286a4b16dadSTom Zanussi static void adf_cleanup_bh(struct adf_accel_dev *accel_dev)
287a4b16dadSTom Zanussi {
288a4b16dadSTom Zanussi 	struct adf_etr_data *priv_data = accel_dev->transport;
289a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
290a4b16dadSTom Zanussi 	int i;
291a4b16dadSTom Zanussi 
292a4b16dadSTom Zanussi 	for (i = 0; i < hw_data->num_banks; i++) {
293a4b16dadSTom Zanussi 		tasklet_disable(&priv_data->banks[i].resp_handler);
294a4b16dadSTom Zanussi 		tasklet_kill(&priv_data->banks[i].resp_handler);
295a4b16dadSTom Zanussi 	}
296a4b16dadSTom Zanussi }
297a4b16dadSTom Zanussi 
298a4b16dadSTom Zanussi /**
299a4b16dadSTom Zanussi  * adf_isr_resource_free() - Free IRQ for acceleration device
300a4b16dadSTom Zanussi  * @accel_dev:  Pointer to acceleration device.
301a4b16dadSTom Zanussi  *
302a4b16dadSTom Zanussi  * Function frees interrupts for acceleration device.
303a4b16dadSTom Zanussi  */
adf_isr_resource_free(struct adf_accel_dev * accel_dev)304a4b16dadSTom Zanussi void adf_isr_resource_free(struct adf_accel_dev *accel_dev)
305a4b16dadSTom Zanussi {
306a4b16dadSTom Zanussi 	adf_free_irqs(accel_dev);
307a4b16dadSTom Zanussi 	adf_cleanup_bh(accel_dev);
308a4b16dadSTom Zanussi 	adf_disable_msix(&accel_dev->accel_pci_dev);
309a4b16dadSTom Zanussi 	adf_isr_free_msix_vectors_data(accel_dev);
310a4b16dadSTom Zanussi }
311a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_isr_resource_free);
312a4b16dadSTom Zanussi 
313a4b16dadSTom Zanussi /**
314a4b16dadSTom Zanussi  * adf_isr_resource_alloc() - Allocate IRQ for acceleration device
315a4b16dadSTom Zanussi  * @accel_dev:  Pointer to acceleration device.
316a4b16dadSTom Zanussi  *
317a4b16dadSTom Zanussi  * Function allocates interrupts for acceleration device.
318a4b16dadSTom Zanussi  *
319a4b16dadSTom Zanussi  * Return: 0 on success, error code otherwise.
320a4b16dadSTom Zanussi  */
adf_isr_resource_alloc(struct adf_accel_dev * accel_dev)321a4b16dadSTom Zanussi int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
322a4b16dadSTom Zanussi {
323a4b16dadSTom Zanussi 	int ret;
324a4b16dadSTom Zanussi 
325a4b16dadSTom Zanussi 	ret = adf_isr_alloc_msix_vectors_data(accel_dev);
326a4b16dadSTom Zanussi 	if (ret)
327a4b16dadSTom Zanussi 		goto err_out;
328a4b16dadSTom Zanussi 
329a4b16dadSTom Zanussi 	ret = adf_enable_msix(accel_dev);
330a4b16dadSTom Zanussi 	if (ret)
331a4b16dadSTom Zanussi 		goto err_free_msix_table;
332a4b16dadSTom Zanussi 
333a4b16dadSTom Zanussi 	ret = adf_setup_bh(accel_dev);
334a4b16dadSTom Zanussi 	if (ret)
335a4b16dadSTom Zanussi 		goto err_disable_msix;
336a4b16dadSTom Zanussi 
337a4b16dadSTom Zanussi 	ret = adf_request_irqs(accel_dev);
338a4b16dadSTom Zanussi 	if (ret)
339a4b16dadSTom Zanussi 		goto err_cleanup_bh;
340a4b16dadSTom Zanussi 
341a4b16dadSTom Zanussi 	return 0;
342a4b16dadSTom Zanussi 
343a4b16dadSTom Zanussi err_cleanup_bh:
344a4b16dadSTom Zanussi 	adf_cleanup_bh(accel_dev);
345a4b16dadSTom Zanussi 
346a4b16dadSTom Zanussi err_disable_msix:
347a4b16dadSTom Zanussi 	adf_disable_msix(&accel_dev->accel_pci_dev);
348a4b16dadSTom Zanussi 
349a4b16dadSTom Zanussi err_free_msix_table:
350a4b16dadSTom Zanussi 	adf_isr_free_msix_vectors_data(accel_dev);
351a4b16dadSTom Zanussi 
352a4b16dadSTom Zanussi err_out:
353a4b16dadSTom Zanussi 	return ret;
354a4b16dadSTom Zanussi }
355a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_isr_resource_alloc);
356a4b16dadSTom Zanussi 
357a4b16dadSTom Zanussi /**
358a4b16dadSTom Zanussi  * adf_init_misc_wq() - Init misc workqueue
359a4b16dadSTom Zanussi  *
360a4b16dadSTom Zanussi  * Function init workqueue 'qat_misc_wq' for general purpose.
361a4b16dadSTom Zanussi  *
362a4b16dadSTom Zanussi  * Return: 0 on success, error code otherwise.
363a4b16dadSTom Zanussi  */
adf_init_misc_wq(void)364a4b16dadSTom Zanussi int __init adf_init_misc_wq(void)
365a4b16dadSTom Zanussi {
366a4b16dadSTom Zanussi 	adf_misc_wq = alloc_workqueue("qat_misc_wq", WQ_MEM_RECLAIM, 0);
367a4b16dadSTom Zanussi 
368a4b16dadSTom Zanussi 	return !adf_misc_wq ? -ENOMEM : 0;
369a4b16dadSTom Zanussi }
370a4b16dadSTom Zanussi 
adf_exit_misc_wq(void)371a4b16dadSTom Zanussi void adf_exit_misc_wq(void)
372a4b16dadSTom Zanussi {
373a4b16dadSTom Zanussi 	if (adf_misc_wq)
374a4b16dadSTom Zanussi 		destroy_workqueue(adf_misc_wq);
375a4b16dadSTom Zanussi 
376a4b16dadSTom Zanussi 	adf_misc_wq = NULL;
377a4b16dadSTom Zanussi }
378a4b16dadSTom Zanussi 
adf_misc_wq_queue_work(struct work_struct * work)379a4b16dadSTom Zanussi bool adf_misc_wq_queue_work(struct work_struct *work)
380a4b16dadSTom Zanussi {
381a4b16dadSTom Zanussi 	return queue_work(adf_misc_wq, work);
382a4b16dadSTom Zanussi }
383*fd77d8daSDamian Muszynski 
adf_misc_wq_queue_delayed_work(struct delayed_work * work,unsigned long delay)384*fd77d8daSDamian Muszynski bool adf_misc_wq_queue_delayed_work(struct delayed_work *work,
385*fd77d8daSDamian Muszynski 				    unsigned long delay)
386*fd77d8daSDamian Muszynski {
387*fd77d8daSDamian Muszynski 	return queue_delayed_work(adf_misc_wq, work, delay);
388*fd77d8daSDamian Muszynski }
389