xref: /freebsd-src/sys/dev/qat/qat_common/adf_vf_isr.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
178ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
278ee8d1cSJulian Grajkowski /* Copyright(c) 2007-2022 Intel Corporation */
378ee8d1cSJulian Grajkowski #include "qat_freebsd.h"
478ee8d1cSJulian Grajkowski #include <sys/kernel.h>
578ee8d1cSJulian Grajkowski #include <sys/systm.h>
6*fdafd315SWarner Losh 
778ee8d1cSJulian Grajkowski #include <sys/types.h>
8266b0663SKrzysztof Zdziarski #include <sys/interrupt.h>
978ee8d1cSJulian Grajkowski #include <dev/pci/pcivar.h>
1078ee8d1cSJulian Grajkowski #include <sys/param.h>
1178ee8d1cSJulian Grajkowski #include <linux/workqueue.h>
1278ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
1378ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
1478ee8d1cSJulian Grajkowski #include "adf_cfg.h"
1578ee8d1cSJulian Grajkowski #include "adf_cfg_strings.h"
1678ee8d1cSJulian Grajkowski #include "adf_cfg_common.h"
1778ee8d1cSJulian Grajkowski #include "adf_transport_access_macros.h"
1878ee8d1cSJulian Grajkowski #include "adf_transport_internal.h"
19266b0663SKrzysztof Zdziarski #include "adf_pfvf_utils.h"
2078ee8d1cSJulian Grajkowski 
2178ee8d1cSJulian Grajkowski static TASKQUEUE_DEFINE_THREAD(qat_vf);
22266b0663SKrzysztof Zdziarski static TASKQUEUE_DEFINE_THREAD(qat_bank_handler);
2378ee8d1cSJulian Grajkowski 
2478ee8d1cSJulian Grajkowski static struct workqueue_struct *adf_vf_stop_wq;
2578ee8d1cSJulian Grajkowski static DEFINE_MUTEX(vf_stop_wq_lock);
2678ee8d1cSJulian Grajkowski 
2778ee8d1cSJulian Grajkowski struct adf_vf_stop_data {
2878ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev;
29266b0663SKrzysztof Zdziarski 	struct work_struct work;
3078ee8d1cSJulian Grajkowski };
3178ee8d1cSJulian Grajkowski 
3278ee8d1cSJulian Grajkowski static int
adf_enable_msi(struct adf_accel_dev * accel_dev)3378ee8d1cSJulian Grajkowski adf_enable_msi(struct adf_accel_dev *accel_dev)
3478ee8d1cSJulian Grajkowski {
3578ee8d1cSJulian Grajkowski 	int stat;
3678ee8d1cSJulian Grajkowski 	int count = 1;
3778ee8d1cSJulian Grajkowski 	stat = pci_alloc_msi(accel_to_pci_dev(accel_dev), &count);
3878ee8d1cSJulian Grajkowski 	if (stat) {
3978ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
4078ee8d1cSJulian Grajkowski 			      "Failed to enable MSI interrupts\n");
4178ee8d1cSJulian Grajkowski 		return stat;
4278ee8d1cSJulian Grajkowski 	}
4378ee8d1cSJulian Grajkowski 
4478ee8d1cSJulian Grajkowski 	return stat;
4578ee8d1cSJulian Grajkowski }
4678ee8d1cSJulian Grajkowski 
4778ee8d1cSJulian Grajkowski static void
adf_disable_msi(struct adf_accel_dev * accel_dev)4878ee8d1cSJulian Grajkowski adf_disable_msi(struct adf_accel_dev *accel_dev)
4978ee8d1cSJulian Grajkowski {
5078ee8d1cSJulian Grajkowski 	device_t pdev = accel_to_pci_dev(accel_dev);
5178ee8d1cSJulian Grajkowski 	pci_release_msi(pdev);
5278ee8d1cSJulian Grajkowski }
5378ee8d1cSJulian Grajkowski 
5478ee8d1cSJulian Grajkowski static void
adf_dev_stop_async(struct work_struct * work)5578ee8d1cSJulian Grajkowski adf_dev_stop_async(struct work_struct *work)
5678ee8d1cSJulian Grajkowski {
5778ee8d1cSJulian Grajkowski 	struct adf_vf_stop_data *stop_data =
58266b0663SKrzysztof Zdziarski 	    container_of(work, struct adf_vf_stop_data, work);
5978ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = stop_data->accel_dev;
60266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
6178ee8d1cSJulian Grajkowski 
6278ee8d1cSJulian Grajkowski 	adf_dev_restarting_notify(accel_dev);
6378ee8d1cSJulian Grajkowski 	adf_dev_stop(accel_dev);
6478ee8d1cSJulian Grajkowski 	adf_dev_shutdown(accel_dev);
6578ee8d1cSJulian Grajkowski 
6678ee8d1cSJulian Grajkowski 	/* Re-enable PF2VF interrupts */
67266b0663SKrzysztof Zdziarski 	hw_data->enable_pf2vf_interrupt(accel_dev);
6878ee8d1cSJulian Grajkowski 	kfree(stop_data);
6978ee8d1cSJulian Grajkowski }
7078ee8d1cSJulian Grajkowski 
71266b0663SKrzysztof Zdziarski int
adf_pf2vf_handle_pf_restarting(struct adf_accel_dev * accel_dev)72266b0663SKrzysztof Zdziarski adf_pf2vf_handle_pf_restarting(struct adf_accel_dev *accel_dev)
7378ee8d1cSJulian Grajkowski {
7478ee8d1cSJulian Grajkowski 	struct adf_vf_stop_data *stop_data;
7578ee8d1cSJulian Grajkowski 
7678ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
7778ee8d1cSJulian Grajkowski 	stop_data = kzalloc(sizeof(*stop_data), GFP_ATOMIC);
7878ee8d1cSJulian Grajkowski 	if (!stop_data) {
7978ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
8078ee8d1cSJulian Grajkowski 			      "Couldn't schedule stop for vf_%d\n",
8178ee8d1cSJulian Grajkowski 			      accel_dev->accel_id);
82266b0663SKrzysztof Zdziarski 		return -ENOMEM;
8378ee8d1cSJulian Grajkowski 	}
8478ee8d1cSJulian Grajkowski 	stop_data->accel_dev = accel_dev;
85266b0663SKrzysztof Zdziarski 	INIT_WORK(&stop_data->work, adf_dev_stop_async);
86266b0663SKrzysztof Zdziarski 	queue_work(adf_vf_stop_wq, &stop_data->work);
87266b0663SKrzysztof Zdziarski 
88266b0663SKrzysztof Zdziarski 	return 0;
8978ee8d1cSJulian Grajkowski }
9078ee8d1cSJulian Grajkowski 
91266b0663SKrzysztof Zdziarski int
adf_pf2vf_handle_pf_rp_reset(struct adf_accel_dev * accel_dev,struct pfvf_message msg)92266b0663SKrzysztof Zdziarski adf_pf2vf_handle_pf_rp_reset(struct adf_accel_dev *accel_dev,
93266b0663SKrzysztof Zdziarski 			     struct pfvf_message msg)
94266b0663SKrzysztof Zdziarski {
95266b0663SKrzysztof Zdziarski 	accel_dev->u1.vf.rpreset_sts = msg.data;
96266b0663SKrzysztof Zdziarski 	if (accel_dev->u1.vf.rpreset_sts == RPRESET_SUCCESS)
97266b0663SKrzysztof Zdziarski 		device_printf(
98266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
99266b0663SKrzysztof Zdziarski 		    "rpreset resp(success) from PF type:0x%x data:0x%x\n",
100266b0663SKrzysztof Zdziarski 		    msg.type,
101266b0663SKrzysztof Zdziarski 		    msg.data);
102266b0663SKrzysztof Zdziarski 	else if (accel_dev->u1.vf.rpreset_sts == RPRESET_NOT_SUPPORTED)
103266b0663SKrzysztof Zdziarski 		device_printf(
104266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
105266b0663SKrzysztof Zdziarski 		    "rpreset resp(not supported) from PF type:0x%x data:0x%x\n",
106266b0663SKrzysztof Zdziarski 		    msg.type,
107266b0663SKrzysztof Zdziarski 		    msg.data);
108266b0663SKrzysztof Zdziarski 	else if (accel_dev->u1.vf.rpreset_sts == RPRESET_INVAL_BANK)
109266b0663SKrzysztof Zdziarski 		device_printf(
110266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
111266b0663SKrzysztof Zdziarski 		    "rpreset resp(invalid bank) from PF type:0x%x data:0x%x\n",
112266b0663SKrzysztof Zdziarski 		    msg.type,
113266b0663SKrzysztof Zdziarski 		    msg.data);
114266b0663SKrzysztof Zdziarski 	else
115266b0663SKrzysztof Zdziarski 		device_printf(
116266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
117266b0663SKrzysztof Zdziarski 		    "rpreset resp(timeout) from PF type:0x%x data:0x%x\nn",
118266b0663SKrzysztof Zdziarski 		    msg.type,
119266b0663SKrzysztof Zdziarski 		    msg.data);
12078ee8d1cSJulian Grajkowski 
121266b0663SKrzysztof Zdziarski 	complete(&accel_dev->u1.vf.msg_received);
122266b0663SKrzysztof Zdziarski 
123266b0663SKrzysztof Zdziarski 	return 0;
124266b0663SKrzysztof Zdziarski }
125266b0663SKrzysztof Zdziarski 
126266b0663SKrzysztof Zdziarski static void
adf_pf2vf_bh_handler(void * data,int pending)127266b0663SKrzysztof Zdziarski adf_pf2vf_bh_handler(void *data, int pending)
128266b0663SKrzysztof Zdziarski {
129266b0663SKrzysztof Zdziarski 	struct adf_accel_dev *accel_dev = data;
130266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
131266b0663SKrzysztof Zdziarski 
132266b0663SKrzysztof Zdziarski 	if (adf_recv_and_handle_pf2vf_msg(accel_dev))
13378ee8d1cSJulian Grajkowski 		/* Re-enable PF2VF interrupts */
134266b0663SKrzysztof Zdziarski 		hw_data->enable_pf2vf_interrupt(accel_dev);
135266b0663SKrzysztof Zdziarski 
13678ee8d1cSJulian Grajkowski 	return;
13778ee8d1cSJulian Grajkowski }
13878ee8d1cSJulian Grajkowski 
13978ee8d1cSJulian Grajkowski static int
adf_setup_pf2vf_bh(struct adf_accel_dev * accel_dev)14078ee8d1cSJulian Grajkowski adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev)
14178ee8d1cSJulian Grajkowski {
14278ee8d1cSJulian Grajkowski 	TASK_INIT(&accel_dev->u1.vf.pf2vf_bh_tasklet,
14378ee8d1cSJulian Grajkowski 		  0,
14478ee8d1cSJulian Grajkowski 		  adf_pf2vf_bh_handler,
14578ee8d1cSJulian Grajkowski 		  accel_dev);
14678ee8d1cSJulian Grajkowski 	mutex_init(&accel_dev->u1.vf.vf2pf_lock);
14778ee8d1cSJulian Grajkowski 
14878ee8d1cSJulian Grajkowski 	return 0;
14978ee8d1cSJulian Grajkowski }
15078ee8d1cSJulian Grajkowski 
15178ee8d1cSJulian Grajkowski static void
adf_cleanup_pf2vf_bh(struct adf_accel_dev * accel_dev)15278ee8d1cSJulian Grajkowski adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev)
15378ee8d1cSJulian Grajkowski {
15478ee8d1cSJulian Grajkowski 	taskqueue_cancel(taskqueue_qat_vf,
15578ee8d1cSJulian Grajkowski 			 &accel_dev->u1.vf.pf2vf_bh_tasklet,
15678ee8d1cSJulian Grajkowski 			 NULL);
15778ee8d1cSJulian Grajkowski 	taskqueue_drain(taskqueue_qat_vf, &accel_dev->u1.vf.pf2vf_bh_tasklet);
15878ee8d1cSJulian Grajkowski 	mutex_destroy(&accel_dev->u1.vf.vf2pf_lock);
15978ee8d1cSJulian Grajkowski }
16078ee8d1cSJulian Grajkowski 
16178ee8d1cSJulian Grajkowski static void
adf_bh_handler(void * data,int pending)162266b0663SKrzysztof Zdziarski adf_bh_handler(void *data, int pending)
163266b0663SKrzysztof Zdziarski {
164266b0663SKrzysztof Zdziarski 	struct adf_etr_bank_data *bank = (void *)data;
165266b0663SKrzysztof Zdziarski 
166266b0663SKrzysztof Zdziarski 	adf_response_handler((uintptr_t)bank);
167266b0663SKrzysztof Zdziarski 
168266b0663SKrzysztof Zdziarski 	return;
169266b0663SKrzysztof Zdziarski }
170266b0663SKrzysztof Zdziarski 
171266b0663SKrzysztof Zdziarski static int
adf_setup_bh(struct adf_accel_dev * accel_dev)172266b0663SKrzysztof Zdziarski adf_setup_bh(struct adf_accel_dev *accel_dev)
173266b0663SKrzysztof Zdziarski {
174266b0663SKrzysztof Zdziarski 	int i = 0;
175266b0663SKrzysztof Zdziarski 	struct adf_etr_data *priv_data = accel_dev->transport;
176266b0663SKrzysztof Zdziarski 
177266b0663SKrzysztof Zdziarski 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) {
178266b0663SKrzysztof Zdziarski 		TASK_INIT(&priv_data->banks[i].resp_handler,
179266b0663SKrzysztof Zdziarski 			  0,
180266b0663SKrzysztof Zdziarski 			  adf_bh_handler,
181266b0663SKrzysztof Zdziarski 			  &priv_data->banks[i]);
182266b0663SKrzysztof Zdziarski 	}
183266b0663SKrzysztof Zdziarski 
184266b0663SKrzysztof Zdziarski 	return 0;
185266b0663SKrzysztof Zdziarski }
186266b0663SKrzysztof Zdziarski 
187266b0663SKrzysztof Zdziarski static void
adf_cleanup_bh(struct adf_accel_dev * accel_dev)188266b0663SKrzysztof Zdziarski adf_cleanup_bh(struct adf_accel_dev *accel_dev)
189266b0663SKrzysztof Zdziarski {
190266b0663SKrzysztof Zdziarski 	int i = 0;
191266b0663SKrzysztof Zdziarski 	struct adf_etr_data *transport;
192266b0663SKrzysztof Zdziarski 
193266b0663SKrzysztof Zdziarski 	if (!accel_dev || !accel_dev->transport)
194266b0663SKrzysztof Zdziarski 		return;
195266b0663SKrzysztof Zdziarski 
196266b0663SKrzysztof Zdziarski 	transport = accel_dev->transport;
197266b0663SKrzysztof Zdziarski 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) {
198266b0663SKrzysztof Zdziarski 		taskqueue_cancel(taskqueue_qat_bank_handler,
199266b0663SKrzysztof Zdziarski 				 &transport->banks[i].resp_handler,
200266b0663SKrzysztof Zdziarski 				 NULL);
201266b0663SKrzysztof Zdziarski 		taskqueue_drain(taskqueue_qat_bank_handler,
202266b0663SKrzysztof Zdziarski 				&transport->banks[i].resp_handler);
203266b0663SKrzysztof Zdziarski 	}
204266b0663SKrzysztof Zdziarski }
205266b0663SKrzysztof Zdziarski 
206266b0663SKrzysztof Zdziarski static void
adf_isr(void * privdata)20778ee8d1cSJulian Grajkowski adf_isr(void *privdata)
20878ee8d1cSJulian Grajkowski {
20978ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = privdata;
21078ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
211266b0663SKrzysztof Zdziarski 	struct adf_hw_csr_ops *csr_ops = &hw_data->csr_info.csr_ops;
212266b0663SKrzysztof Zdziarski 	int int_active_bundles = 0;
213266b0663SKrzysztof Zdziarski 	int i = 0;
21478ee8d1cSJulian Grajkowski 
21578ee8d1cSJulian Grajkowski 	/* Check for PF2VF interrupt */
216266b0663SKrzysztof Zdziarski 	if (hw_data->interrupt_active_pf2vf(accel_dev)) {
21778ee8d1cSJulian Grajkowski 		/* Disable PF to VF interrupt */
218266b0663SKrzysztof Zdziarski 		hw_data->disable_pf2vf_interrupt(accel_dev);
21978ee8d1cSJulian Grajkowski 		/* Schedule tasklet to handle interrupt BH */
22078ee8d1cSJulian Grajkowski 		taskqueue_enqueue(taskqueue_qat_vf,
22178ee8d1cSJulian Grajkowski 				  &accel_dev->u1.vf.pf2vf_bh_tasklet);
22278ee8d1cSJulian Grajkowski 	}
22378ee8d1cSJulian Grajkowski 
224266b0663SKrzysztof Zdziarski 	if (hw_data->get_int_active_bundles)
225266b0663SKrzysztof Zdziarski 		int_active_bundles = hw_data->get_int_active_bundles(accel_dev);
226266b0663SKrzysztof Zdziarski 
227266b0663SKrzysztof Zdziarski 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) {
228266b0663SKrzysztof Zdziarski 		if (int_active_bundles & BIT(i)) {
22978ee8d1cSJulian Grajkowski 			struct adf_etr_data *etr_data = accel_dev->transport;
230266b0663SKrzysztof Zdziarski 			struct adf_etr_bank_data *bank = &etr_data->banks[i];
23178ee8d1cSJulian Grajkowski 
23278ee8d1cSJulian Grajkowski 			/* Disable Flag and Coalesce Ring Interrupts */
233266b0663SKrzysztof Zdziarski 			csr_ops->write_csr_int_flag_and_col(bank->csr_addr,
23478ee8d1cSJulian Grajkowski 							    bank->bank_number,
23578ee8d1cSJulian Grajkowski 							    0);
236266b0663SKrzysztof Zdziarski 			/* Schedule tasklet to handle interrupt BH */
237266b0663SKrzysztof Zdziarski 			taskqueue_enqueue(taskqueue_qat_bank_handler,
238266b0663SKrzysztof Zdziarski 					  &bank->resp_handler);
23978ee8d1cSJulian Grajkowski 		}
240266b0663SKrzysztof Zdziarski 	}
24178ee8d1cSJulian Grajkowski }
24278ee8d1cSJulian Grajkowski 
24378ee8d1cSJulian Grajkowski static int
adf_request_msi_irq(struct adf_accel_dev * accel_dev)24478ee8d1cSJulian Grajkowski adf_request_msi_irq(struct adf_accel_dev *accel_dev)
24578ee8d1cSJulian Grajkowski {
24678ee8d1cSJulian Grajkowski 	device_t pdev = accel_to_pci_dev(accel_dev);
24778ee8d1cSJulian Grajkowski 	int ret;
24878ee8d1cSJulian Grajkowski 	int rid = 1;
249266b0663SKrzysztof Zdziarski 	int cpu;
250266b0663SKrzysztof Zdziarski 
25178ee8d1cSJulian Grajkowski 	accel_dev->u1.vf.irq =
25278ee8d1cSJulian Grajkowski 	    bus_alloc_resource_any(pdev, SYS_RES_IRQ, &rid, RF_ACTIVE);
25378ee8d1cSJulian Grajkowski 	if (accel_dev->u1.vf.irq == NULL) {
25478ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "failed to allocate IRQ\n");
25578ee8d1cSJulian Grajkowski 		return ENXIO;
25678ee8d1cSJulian Grajkowski 	}
25778ee8d1cSJulian Grajkowski 	ret = bus_setup_intr(pdev,
25878ee8d1cSJulian Grajkowski 			     accel_dev->u1.vf.irq,
25978ee8d1cSJulian Grajkowski 			     INTR_TYPE_MISC | INTR_MPSAFE,
26078ee8d1cSJulian Grajkowski 			     NULL,
26178ee8d1cSJulian Grajkowski 			     adf_isr,
26278ee8d1cSJulian Grajkowski 			     accel_dev,
26378ee8d1cSJulian Grajkowski 			     &accel_dev->u1.vf.cookie);
26478ee8d1cSJulian Grajkowski 	if (ret) {
265266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev), "failed to enable irq\n");
266266b0663SKrzysztof Zdziarski 		goto errout;
267266b0663SKrzysztof Zdziarski 	}
268266b0663SKrzysztof Zdziarski 
269266b0663SKrzysztof Zdziarski 	cpu = accel_dev->accel_id % num_online_cpus();
270266b0663SKrzysztof Zdziarski 	ret = bus_bind_intr(pdev, accel_dev->u1.vf.irq, cpu);
271266b0663SKrzysztof Zdziarski 	if (ret) {
27278ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
273266b0663SKrzysztof Zdziarski 			      "failed to bind IRQ handler to cpu core\n");
274266b0663SKrzysztof Zdziarski 		goto errout;
27578ee8d1cSJulian Grajkowski 	}
276266b0663SKrzysztof Zdziarski 	accel_dev->u1.vf.irq_enabled = true;
27778ee8d1cSJulian Grajkowski 
278266b0663SKrzysztof Zdziarski 	return ret;
279266b0663SKrzysztof Zdziarski errout:
280266b0663SKrzysztof Zdziarski 	bus_free_resource(pdev, SYS_RES_IRQ, accel_dev->u1.vf.irq);
28178ee8d1cSJulian Grajkowski 
282266b0663SKrzysztof Zdziarski 	return ret;
28378ee8d1cSJulian Grajkowski }
28478ee8d1cSJulian Grajkowski 
28578ee8d1cSJulian Grajkowski /**
28678ee8d1cSJulian Grajkowski  * adf_vf_isr_resource_free() - Free IRQ for acceleration device
28778ee8d1cSJulian Grajkowski  * @accel_dev:  Pointer to acceleration device.
28878ee8d1cSJulian Grajkowski  *
28978ee8d1cSJulian Grajkowski  * Function frees interrupts for acceleration device virtual function.
29078ee8d1cSJulian Grajkowski  */
29178ee8d1cSJulian Grajkowski void
adf_vf_isr_resource_free(struct adf_accel_dev * accel_dev)29278ee8d1cSJulian Grajkowski adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev)
29378ee8d1cSJulian Grajkowski {
29478ee8d1cSJulian Grajkowski 	device_t pdev = accel_to_pci_dev(accel_dev);
295266b0663SKrzysztof Zdziarski 
296266b0663SKrzysztof Zdziarski 	if (accel_dev->u1.vf.irq_enabled) {
297266b0663SKrzysztof Zdziarski 		bus_teardown_intr(pdev,
298266b0663SKrzysztof Zdziarski 				  accel_dev->u1.vf.irq,
299266b0663SKrzysztof Zdziarski 				  accel_dev->u1.vf.cookie);
30078ee8d1cSJulian Grajkowski 		bus_free_resource(pdev, SYS_RES_IRQ, accel_dev->u1.vf.irq);
301266b0663SKrzysztof Zdziarski 	}
30278ee8d1cSJulian Grajkowski 	adf_cleanup_bh(accel_dev);
30378ee8d1cSJulian Grajkowski 	adf_cleanup_pf2vf_bh(accel_dev);
30478ee8d1cSJulian Grajkowski 	adf_disable_msi(accel_dev);
30578ee8d1cSJulian Grajkowski }
30678ee8d1cSJulian Grajkowski 
30778ee8d1cSJulian Grajkowski /**
30878ee8d1cSJulian Grajkowski  * adf_vf_isr_resource_alloc() - Allocate IRQ for acceleration device
30978ee8d1cSJulian Grajkowski  * @accel_dev:  Pointer to acceleration device.
31078ee8d1cSJulian Grajkowski  *
31178ee8d1cSJulian Grajkowski  * Function allocates interrupts for acceleration device virtual function.
31278ee8d1cSJulian Grajkowski  *
31378ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
31478ee8d1cSJulian Grajkowski  */
31578ee8d1cSJulian Grajkowski int
adf_vf_isr_resource_alloc(struct adf_accel_dev * accel_dev)31678ee8d1cSJulian Grajkowski adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
31778ee8d1cSJulian Grajkowski {
31878ee8d1cSJulian Grajkowski 	if (adf_enable_msi(accel_dev))
31978ee8d1cSJulian Grajkowski 		goto err_out;
32078ee8d1cSJulian Grajkowski 
32178ee8d1cSJulian Grajkowski 	if (adf_setup_pf2vf_bh(accel_dev))
322266b0663SKrzysztof Zdziarski 		goto err_disable_msi;
32378ee8d1cSJulian Grajkowski 
32478ee8d1cSJulian Grajkowski 	if (adf_setup_bh(accel_dev))
32578ee8d1cSJulian Grajkowski 		goto err_out;
32678ee8d1cSJulian Grajkowski 
32778ee8d1cSJulian Grajkowski 	if (adf_request_msi_irq(accel_dev))
328266b0663SKrzysztof Zdziarski 		goto err_disable_msi;
32978ee8d1cSJulian Grajkowski 
33078ee8d1cSJulian Grajkowski 	return 0;
331266b0663SKrzysztof Zdziarski 
332266b0663SKrzysztof Zdziarski err_disable_msi:
333266b0663SKrzysztof Zdziarski 	adf_disable_msi(accel_dev);
334266b0663SKrzysztof Zdziarski 
33578ee8d1cSJulian Grajkowski err_out:
336266b0663SKrzysztof Zdziarski 	return -EFAULT;
33778ee8d1cSJulian Grajkowski }
33878ee8d1cSJulian Grajkowski 
33978ee8d1cSJulian Grajkowski /**
34078ee8d1cSJulian Grajkowski  * adf_flush_vf_wq() - Flush workqueue for VF
341266b0663SKrzysztof Zdziarski  * @accel_dev:  Pointer to acceleration device.
34278ee8d1cSJulian Grajkowski  *
343266b0663SKrzysztof Zdziarski  * Function disables the PF/VF interrupts on the VF so that no new messages
344266b0663SKrzysztof Zdziarski  * are received and flushes the workqueue 'adf_vf_stop_wq'.
34578ee8d1cSJulian Grajkowski  *
34678ee8d1cSJulian Grajkowski  * Return: void.
34778ee8d1cSJulian Grajkowski  */
34878ee8d1cSJulian Grajkowski void
adf_flush_vf_wq(struct adf_accel_dev * accel_dev)349266b0663SKrzysztof Zdziarski adf_flush_vf_wq(struct adf_accel_dev *accel_dev)
35078ee8d1cSJulian Grajkowski {
351266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
352266b0663SKrzysztof Zdziarski 
353266b0663SKrzysztof Zdziarski 	hw_data->disable_pf2vf_interrupt(accel_dev);
354266b0663SKrzysztof Zdziarski 
35578ee8d1cSJulian Grajkowski 	if (adf_vf_stop_wq)
35678ee8d1cSJulian Grajkowski 		flush_workqueue(adf_vf_stop_wq);
35778ee8d1cSJulian Grajkowski }
35878ee8d1cSJulian Grajkowski 
35978ee8d1cSJulian Grajkowski /**
36078ee8d1cSJulian Grajkowski  * adf_init_vf_wq() - Init workqueue for VF
36178ee8d1cSJulian Grajkowski  *
36278ee8d1cSJulian Grajkowski  * Function init workqueue 'adf_vf_stop_wq' for VF.
36378ee8d1cSJulian Grajkowski  *
36478ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
36578ee8d1cSJulian Grajkowski  */
36678ee8d1cSJulian Grajkowski int
adf_init_vf_wq(void)36778ee8d1cSJulian Grajkowski adf_init_vf_wq(void)
36878ee8d1cSJulian Grajkowski {
36978ee8d1cSJulian Grajkowski 	int ret = 0;
37078ee8d1cSJulian Grajkowski 
37178ee8d1cSJulian Grajkowski 	mutex_lock(&vf_stop_wq_lock);
37278ee8d1cSJulian Grajkowski 	if (!adf_vf_stop_wq)
37378ee8d1cSJulian Grajkowski 		adf_vf_stop_wq =
37478ee8d1cSJulian Grajkowski 		    alloc_workqueue("adf_vf_stop_wq", WQ_MEM_RECLAIM, 0);
37578ee8d1cSJulian Grajkowski 
37678ee8d1cSJulian Grajkowski 	if (!adf_vf_stop_wq)
37778ee8d1cSJulian Grajkowski 		ret = ENOMEM;
37878ee8d1cSJulian Grajkowski 
37978ee8d1cSJulian Grajkowski 	mutex_unlock(&vf_stop_wq_lock);
38078ee8d1cSJulian Grajkowski 	return ret;
38178ee8d1cSJulian Grajkowski }
38278ee8d1cSJulian Grajkowski 
38378ee8d1cSJulian Grajkowski void
adf_exit_vf_wq(void)38478ee8d1cSJulian Grajkowski adf_exit_vf_wq(void)
38578ee8d1cSJulian Grajkowski {
386266b0663SKrzysztof Zdziarski 	if (adf_vf_stop_wq)
38778ee8d1cSJulian Grajkowski 		destroy_workqueue(adf_vf_stop_wq);
388266b0663SKrzysztof Zdziarski 
38978ee8d1cSJulian Grajkowski 	adf_vf_stop_wq = NULL;
39078ee8d1cSJulian Grajkowski }
391