xref: /freebsd/sys/dev/qat/qat_common/adf_vf_isr.c (revision ded037e65e5239671b1292ec987a2e0894b217b5)
178ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
2*ded037e6SHareshx Sankar Raj /* Copyright(c) 2007-2025 Intel Corporation */
378ee8d1cSJulian Grajkowski #include "qat_freebsd.h"
478ee8d1cSJulian Grajkowski #include <sys/kernel.h>
578ee8d1cSJulian Grajkowski #include <sys/systm.h>
6fdafd315SWarner 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"
20*ded037e6SHareshx Sankar Raj #include "adf_pfvf_vf_msg.h"
2178ee8d1cSJulian Grajkowski 
2278ee8d1cSJulian Grajkowski static TASKQUEUE_DEFINE_THREAD(qat_vf);
23266b0663SKrzysztof Zdziarski static TASKQUEUE_DEFINE_THREAD(qat_bank_handler);
2478ee8d1cSJulian Grajkowski 
2578ee8d1cSJulian Grajkowski static struct workqueue_struct *adf_vf_stop_wq;
2678ee8d1cSJulian Grajkowski static DEFINE_MUTEX(vf_stop_wq_lock);
2778ee8d1cSJulian Grajkowski 
2878ee8d1cSJulian Grajkowski struct adf_vf_stop_data {
2978ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev;
30266b0663SKrzysztof Zdziarski 	struct work_struct work;
3178ee8d1cSJulian Grajkowski };
3278ee8d1cSJulian Grajkowski 
3378ee8d1cSJulian Grajkowski static int
adf_enable_msi(struct adf_accel_dev * accel_dev)3478ee8d1cSJulian Grajkowski adf_enable_msi(struct adf_accel_dev *accel_dev)
3578ee8d1cSJulian Grajkowski {
3678ee8d1cSJulian Grajkowski 	int stat;
3778ee8d1cSJulian Grajkowski 	int count = 1;
3878ee8d1cSJulian Grajkowski 	stat = pci_alloc_msi(accel_to_pci_dev(accel_dev), &count);
3978ee8d1cSJulian Grajkowski 	if (stat) {
4078ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
4178ee8d1cSJulian Grajkowski 			      "Failed to enable MSI interrupts\n");
4278ee8d1cSJulian Grajkowski 		return stat;
4378ee8d1cSJulian Grajkowski 	}
4478ee8d1cSJulian Grajkowski 
4578ee8d1cSJulian Grajkowski 	return stat;
4678ee8d1cSJulian Grajkowski }
4778ee8d1cSJulian Grajkowski 
4878ee8d1cSJulian Grajkowski static void
adf_disable_msi(struct adf_accel_dev * accel_dev)4978ee8d1cSJulian Grajkowski adf_disable_msi(struct adf_accel_dev *accel_dev)
5078ee8d1cSJulian Grajkowski {
5178ee8d1cSJulian Grajkowski 	device_t pdev = accel_to_pci_dev(accel_dev);
5278ee8d1cSJulian Grajkowski 	pci_release_msi(pdev);
5378ee8d1cSJulian Grajkowski }
5478ee8d1cSJulian Grajkowski 
5578ee8d1cSJulian Grajkowski static void
adf_dev_stop_async(struct work_struct * work)5678ee8d1cSJulian Grajkowski adf_dev_stop_async(struct work_struct *work)
5778ee8d1cSJulian Grajkowski {
5878ee8d1cSJulian Grajkowski 	struct adf_vf_stop_data *stop_data =
59266b0663SKrzysztof Zdziarski 	    container_of(work, struct adf_vf_stop_data, work);
6078ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = stop_data->accel_dev;
61266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
6278ee8d1cSJulian Grajkowski 
6378ee8d1cSJulian Grajkowski 	adf_dev_restarting_notify(accel_dev);
6478ee8d1cSJulian Grajkowski 	adf_dev_stop(accel_dev);
6578ee8d1cSJulian Grajkowski 	adf_dev_shutdown(accel_dev);
6678ee8d1cSJulian Grajkowski 
6778ee8d1cSJulian Grajkowski 	/* Re-enable PF2VF interrupts */
68266b0663SKrzysztof Zdziarski 	hw_data->enable_pf2vf_interrupt(accel_dev);
69*ded037e6SHareshx Sankar Raj 	adf_vf2pf_restarting_complete(accel_dev);
7078ee8d1cSJulian Grajkowski 	kfree(stop_data);
7178ee8d1cSJulian Grajkowski }
7278ee8d1cSJulian Grajkowski 
73266b0663SKrzysztof Zdziarski int
adf_pf2vf_handle_pf_restarting(struct adf_accel_dev * accel_dev)74266b0663SKrzysztof Zdziarski adf_pf2vf_handle_pf_restarting(struct adf_accel_dev *accel_dev)
7578ee8d1cSJulian Grajkowski {
7678ee8d1cSJulian Grajkowski 	struct adf_vf_stop_data *stop_data;
7778ee8d1cSJulian Grajkowski 
7878ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
7978ee8d1cSJulian Grajkowski 	stop_data = kzalloc(sizeof(*stop_data), GFP_ATOMIC);
8078ee8d1cSJulian Grajkowski 	if (!stop_data) {
8178ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
8278ee8d1cSJulian Grajkowski 			      "Couldn't schedule stop for vf_%d\n",
8378ee8d1cSJulian Grajkowski 			      accel_dev->accel_id);
84266b0663SKrzysztof Zdziarski 		return -ENOMEM;
8578ee8d1cSJulian Grajkowski 	}
8678ee8d1cSJulian Grajkowski 	stop_data->accel_dev = accel_dev;
87266b0663SKrzysztof Zdziarski 	INIT_WORK(&stop_data->work, adf_dev_stop_async);
88266b0663SKrzysztof Zdziarski 	queue_work(adf_vf_stop_wq, &stop_data->work);
89266b0663SKrzysztof Zdziarski 
90266b0663SKrzysztof Zdziarski 	return 0;
9178ee8d1cSJulian Grajkowski }
9278ee8d1cSJulian Grajkowski 
93266b0663SKrzysztof Zdziarski int
adf_pf2vf_handle_pf_rp_reset(struct adf_accel_dev * accel_dev,struct pfvf_message msg)94266b0663SKrzysztof Zdziarski adf_pf2vf_handle_pf_rp_reset(struct adf_accel_dev *accel_dev,
95266b0663SKrzysztof Zdziarski 			     struct pfvf_message msg)
96266b0663SKrzysztof Zdziarski {
97266b0663SKrzysztof Zdziarski 	accel_dev->u1.vf.rpreset_sts = msg.data;
98266b0663SKrzysztof Zdziarski 	if (accel_dev->u1.vf.rpreset_sts == RPRESET_SUCCESS)
99266b0663SKrzysztof Zdziarski 		device_printf(
100266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
101266b0663SKrzysztof Zdziarski 		    "rpreset resp(success) from PF type:0x%x data:0x%x\n",
102266b0663SKrzysztof Zdziarski 		    msg.type,
103266b0663SKrzysztof Zdziarski 		    msg.data);
104266b0663SKrzysztof Zdziarski 	else if (accel_dev->u1.vf.rpreset_sts == RPRESET_NOT_SUPPORTED)
105266b0663SKrzysztof Zdziarski 		device_printf(
106266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
107266b0663SKrzysztof Zdziarski 		    "rpreset resp(not supported) from PF type:0x%x data:0x%x\n",
108266b0663SKrzysztof Zdziarski 		    msg.type,
109266b0663SKrzysztof Zdziarski 		    msg.data);
110266b0663SKrzysztof Zdziarski 	else if (accel_dev->u1.vf.rpreset_sts == RPRESET_INVAL_BANK)
111266b0663SKrzysztof Zdziarski 		device_printf(
112266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
113266b0663SKrzysztof Zdziarski 		    "rpreset resp(invalid bank) from PF type:0x%x data:0x%x\n",
114266b0663SKrzysztof Zdziarski 		    msg.type,
115266b0663SKrzysztof Zdziarski 		    msg.data);
116266b0663SKrzysztof Zdziarski 	else
117266b0663SKrzysztof Zdziarski 		device_printf(
118266b0663SKrzysztof Zdziarski 		    GET_DEV(accel_dev),
119266b0663SKrzysztof Zdziarski 		    "rpreset resp(timeout) from PF type:0x%x data:0x%x\nn",
120266b0663SKrzysztof Zdziarski 		    msg.type,
121266b0663SKrzysztof Zdziarski 		    msg.data);
12278ee8d1cSJulian Grajkowski 
123266b0663SKrzysztof Zdziarski 	complete(&accel_dev->u1.vf.msg_received);
124266b0663SKrzysztof Zdziarski 
125266b0663SKrzysztof Zdziarski 	return 0;
126266b0663SKrzysztof Zdziarski }
127266b0663SKrzysztof Zdziarski 
128*ded037e6SHareshx Sankar Raj int
adf_pf2vf_handle_pf_error(struct adf_accel_dev * accel_dev)129*ded037e6SHareshx Sankar Raj adf_pf2vf_handle_pf_error(struct adf_accel_dev *accel_dev)
130*ded037e6SHareshx Sankar Raj {
131*ded037e6SHareshx Sankar Raj 	device_printf(GET_DEV(accel_dev), "Fatal error received from PF\n");
132*ded037e6SHareshx Sankar Raj 
133*ded037e6SHareshx Sankar Raj 	if (adf_notify_fatal_error(accel_dev))
134*ded037e6SHareshx Sankar Raj 		device_printf(GET_DEV(accel_dev), "Couldn't notify fatal error\n");
135*ded037e6SHareshx Sankar Raj 
136*ded037e6SHareshx Sankar Raj 	return 0;
137*ded037e6SHareshx Sankar Raj }
138*ded037e6SHareshx Sankar Raj 
139266b0663SKrzysztof Zdziarski static void
adf_pf2vf_bh_handler(void * data,int pending)140266b0663SKrzysztof Zdziarski adf_pf2vf_bh_handler(void *data, int pending)
141266b0663SKrzysztof Zdziarski {
142266b0663SKrzysztof Zdziarski 	struct adf_accel_dev *accel_dev = data;
143266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
144266b0663SKrzysztof Zdziarski 
145266b0663SKrzysztof Zdziarski 	if (adf_recv_and_handle_pf2vf_msg(accel_dev))
14678ee8d1cSJulian Grajkowski 		/* Re-enable PF2VF interrupts */
147266b0663SKrzysztof Zdziarski 		hw_data->enable_pf2vf_interrupt(accel_dev);
148266b0663SKrzysztof Zdziarski 
14978ee8d1cSJulian Grajkowski 	return;
15078ee8d1cSJulian Grajkowski }
15178ee8d1cSJulian Grajkowski 
15278ee8d1cSJulian Grajkowski static int
adf_setup_pf2vf_bh(struct adf_accel_dev * accel_dev)15378ee8d1cSJulian Grajkowski adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev)
15478ee8d1cSJulian Grajkowski {
15578ee8d1cSJulian Grajkowski 	TASK_INIT(&accel_dev->u1.vf.pf2vf_bh_tasklet,
15678ee8d1cSJulian Grajkowski 		  0,
15778ee8d1cSJulian Grajkowski 		  adf_pf2vf_bh_handler,
15878ee8d1cSJulian Grajkowski 		  accel_dev);
15978ee8d1cSJulian Grajkowski 	mutex_init(&accel_dev->u1.vf.vf2pf_lock);
16078ee8d1cSJulian Grajkowski 
16178ee8d1cSJulian Grajkowski 	return 0;
16278ee8d1cSJulian Grajkowski }
16378ee8d1cSJulian Grajkowski 
16478ee8d1cSJulian Grajkowski static void
adf_cleanup_pf2vf_bh(struct adf_accel_dev * accel_dev)16578ee8d1cSJulian Grajkowski adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev)
16678ee8d1cSJulian Grajkowski {
16778ee8d1cSJulian Grajkowski 	taskqueue_cancel(taskqueue_qat_vf,
16878ee8d1cSJulian Grajkowski 			 &accel_dev->u1.vf.pf2vf_bh_tasklet,
16978ee8d1cSJulian Grajkowski 			 NULL);
17078ee8d1cSJulian Grajkowski 	taskqueue_drain(taskqueue_qat_vf, &accel_dev->u1.vf.pf2vf_bh_tasklet);
17178ee8d1cSJulian Grajkowski 	mutex_destroy(&accel_dev->u1.vf.vf2pf_lock);
17278ee8d1cSJulian Grajkowski }
17378ee8d1cSJulian Grajkowski 
17478ee8d1cSJulian Grajkowski static void
adf_bh_handler(void * data,int pending)175266b0663SKrzysztof Zdziarski adf_bh_handler(void *data, int pending)
176266b0663SKrzysztof Zdziarski {
177266b0663SKrzysztof Zdziarski 	struct adf_etr_bank_data *bank = (void *)data;
178266b0663SKrzysztof Zdziarski 
179266b0663SKrzysztof Zdziarski 	adf_response_handler((uintptr_t)bank);
180266b0663SKrzysztof Zdziarski 
181266b0663SKrzysztof Zdziarski 	return;
182266b0663SKrzysztof Zdziarski }
183266b0663SKrzysztof Zdziarski 
184266b0663SKrzysztof Zdziarski static int
adf_setup_bh(struct adf_accel_dev * accel_dev)185266b0663SKrzysztof Zdziarski adf_setup_bh(struct adf_accel_dev *accel_dev)
186266b0663SKrzysztof Zdziarski {
187266b0663SKrzysztof Zdziarski 	int i = 0;
188266b0663SKrzysztof Zdziarski 	struct adf_etr_data *priv_data = accel_dev->transport;
189266b0663SKrzysztof Zdziarski 
190266b0663SKrzysztof Zdziarski 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) {
191266b0663SKrzysztof Zdziarski 		TASK_INIT(&priv_data->banks[i].resp_handler,
192266b0663SKrzysztof Zdziarski 			  0,
193266b0663SKrzysztof Zdziarski 			  adf_bh_handler,
194266b0663SKrzysztof Zdziarski 			  &priv_data->banks[i]);
195266b0663SKrzysztof Zdziarski 	}
196266b0663SKrzysztof Zdziarski 
197266b0663SKrzysztof Zdziarski 	return 0;
198266b0663SKrzysztof Zdziarski }
199266b0663SKrzysztof Zdziarski 
200266b0663SKrzysztof Zdziarski static void
adf_cleanup_bh(struct adf_accel_dev * accel_dev)201266b0663SKrzysztof Zdziarski adf_cleanup_bh(struct adf_accel_dev *accel_dev)
202266b0663SKrzysztof Zdziarski {
203266b0663SKrzysztof Zdziarski 	int i = 0;
204266b0663SKrzysztof Zdziarski 	struct adf_etr_data *transport;
205266b0663SKrzysztof Zdziarski 
206266b0663SKrzysztof Zdziarski 	if (!accel_dev || !accel_dev->transport)
207266b0663SKrzysztof Zdziarski 		return;
208266b0663SKrzysztof Zdziarski 
209266b0663SKrzysztof Zdziarski 	transport = accel_dev->transport;
210266b0663SKrzysztof Zdziarski 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) {
211266b0663SKrzysztof Zdziarski 		taskqueue_cancel(taskqueue_qat_bank_handler,
212266b0663SKrzysztof Zdziarski 				 &transport->banks[i].resp_handler,
213266b0663SKrzysztof Zdziarski 				 NULL);
214266b0663SKrzysztof Zdziarski 		taskqueue_drain(taskqueue_qat_bank_handler,
215266b0663SKrzysztof Zdziarski 				&transport->banks[i].resp_handler);
216266b0663SKrzysztof Zdziarski 	}
217266b0663SKrzysztof Zdziarski }
218266b0663SKrzysztof Zdziarski 
219266b0663SKrzysztof Zdziarski static void
adf_isr(void * privdata)22078ee8d1cSJulian Grajkowski adf_isr(void *privdata)
22178ee8d1cSJulian Grajkowski {
22278ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = privdata;
22378ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
224266b0663SKrzysztof Zdziarski 	struct adf_hw_csr_ops *csr_ops = &hw_data->csr_info.csr_ops;
225266b0663SKrzysztof Zdziarski 	int int_active_bundles = 0;
226266b0663SKrzysztof Zdziarski 	int i = 0;
22778ee8d1cSJulian Grajkowski 
22878ee8d1cSJulian Grajkowski 	/* Check for PF2VF interrupt */
229266b0663SKrzysztof Zdziarski 	if (hw_data->interrupt_active_pf2vf(accel_dev)) {
23078ee8d1cSJulian Grajkowski 		/* Disable PF to VF interrupt */
231266b0663SKrzysztof Zdziarski 		hw_data->disable_pf2vf_interrupt(accel_dev);
23278ee8d1cSJulian Grajkowski 		/* Schedule tasklet to handle interrupt BH */
23378ee8d1cSJulian Grajkowski 		taskqueue_enqueue(taskqueue_qat_vf,
23478ee8d1cSJulian Grajkowski 				  &accel_dev->u1.vf.pf2vf_bh_tasklet);
23578ee8d1cSJulian Grajkowski 	}
23678ee8d1cSJulian Grajkowski 
237266b0663SKrzysztof Zdziarski 	if (hw_data->get_int_active_bundles)
238266b0663SKrzysztof Zdziarski 		int_active_bundles = hw_data->get_int_active_bundles(accel_dev);
239266b0663SKrzysztof Zdziarski 
240266b0663SKrzysztof Zdziarski 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) {
241266b0663SKrzysztof Zdziarski 		if (int_active_bundles & BIT(i)) {
24278ee8d1cSJulian Grajkowski 			struct adf_etr_data *etr_data = accel_dev->transport;
243266b0663SKrzysztof Zdziarski 			struct adf_etr_bank_data *bank = &etr_data->banks[i];
24478ee8d1cSJulian Grajkowski 
24578ee8d1cSJulian Grajkowski 			/* Disable Flag and Coalesce Ring Interrupts */
246266b0663SKrzysztof Zdziarski 			csr_ops->write_csr_int_flag_and_col(bank->csr_addr,
24778ee8d1cSJulian Grajkowski 							    bank->bank_number,
24878ee8d1cSJulian Grajkowski 							    0);
249266b0663SKrzysztof Zdziarski 			/* Schedule tasklet to handle interrupt BH */
250266b0663SKrzysztof Zdziarski 			taskqueue_enqueue(taskqueue_qat_bank_handler,
251266b0663SKrzysztof Zdziarski 					  &bank->resp_handler);
25278ee8d1cSJulian Grajkowski 		}
253266b0663SKrzysztof Zdziarski 	}
25478ee8d1cSJulian Grajkowski }
25578ee8d1cSJulian Grajkowski 
25678ee8d1cSJulian Grajkowski static int
adf_request_msi_irq(struct adf_accel_dev * accel_dev)25778ee8d1cSJulian Grajkowski adf_request_msi_irq(struct adf_accel_dev *accel_dev)
25878ee8d1cSJulian Grajkowski {
25978ee8d1cSJulian Grajkowski 	device_t pdev = accel_to_pci_dev(accel_dev);
26078ee8d1cSJulian Grajkowski 	int ret;
26178ee8d1cSJulian Grajkowski 	int rid = 1;
262266b0663SKrzysztof Zdziarski 	int cpu;
263266b0663SKrzysztof Zdziarski 
26478ee8d1cSJulian Grajkowski 	accel_dev->u1.vf.irq =
26578ee8d1cSJulian Grajkowski 	    bus_alloc_resource_any(pdev, SYS_RES_IRQ, &rid, RF_ACTIVE);
26678ee8d1cSJulian Grajkowski 	if (accel_dev->u1.vf.irq == NULL) {
26778ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "failed to allocate IRQ\n");
26878ee8d1cSJulian Grajkowski 		return ENXIO;
26978ee8d1cSJulian Grajkowski 	}
27078ee8d1cSJulian Grajkowski 	ret = bus_setup_intr(pdev,
27178ee8d1cSJulian Grajkowski 			     accel_dev->u1.vf.irq,
27278ee8d1cSJulian Grajkowski 			     INTR_TYPE_MISC | INTR_MPSAFE,
27378ee8d1cSJulian Grajkowski 			     NULL,
27478ee8d1cSJulian Grajkowski 			     adf_isr,
27578ee8d1cSJulian Grajkowski 			     accel_dev,
27678ee8d1cSJulian Grajkowski 			     &accel_dev->u1.vf.cookie);
27778ee8d1cSJulian Grajkowski 	if (ret) {
278266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev), "failed to enable irq\n");
279266b0663SKrzysztof Zdziarski 		goto errout;
280266b0663SKrzysztof Zdziarski 	}
281266b0663SKrzysztof Zdziarski 
282266b0663SKrzysztof Zdziarski 	cpu = accel_dev->accel_id % num_online_cpus();
283266b0663SKrzysztof Zdziarski 	ret = bus_bind_intr(pdev, accel_dev->u1.vf.irq, cpu);
284266b0663SKrzysztof Zdziarski 	if (ret) {
28578ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
286266b0663SKrzysztof Zdziarski 			      "failed to bind IRQ handler to cpu core\n");
287266b0663SKrzysztof Zdziarski 		goto errout;
28878ee8d1cSJulian Grajkowski 	}
289266b0663SKrzysztof Zdziarski 	accel_dev->u1.vf.irq_enabled = true;
29078ee8d1cSJulian Grajkowski 
291266b0663SKrzysztof Zdziarski 	return ret;
292266b0663SKrzysztof Zdziarski errout:
293266b0663SKrzysztof Zdziarski 	bus_free_resource(pdev, SYS_RES_IRQ, accel_dev->u1.vf.irq);
29478ee8d1cSJulian Grajkowski 
295266b0663SKrzysztof Zdziarski 	return ret;
29678ee8d1cSJulian Grajkowski }
29778ee8d1cSJulian Grajkowski 
29878ee8d1cSJulian Grajkowski /**
29978ee8d1cSJulian Grajkowski  * adf_vf_isr_resource_free() - Free IRQ for acceleration device
30078ee8d1cSJulian Grajkowski  * @accel_dev:  Pointer to acceleration device.
30178ee8d1cSJulian Grajkowski  *
30278ee8d1cSJulian Grajkowski  * Function frees interrupts for acceleration device virtual function.
30378ee8d1cSJulian Grajkowski  */
30478ee8d1cSJulian Grajkowski void
adf_vf_isr_resource_free(struct adf_accel_dev * accel_dev)30578ee8d1cSJulian Grajkowski adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev)
30678ee8d1cSJulian Grajkowski {
30778ee8d1cSJulian Grajkowski 	device_t pdev = accel_to_pci_dev(accel_dev);
308266b0663SKrzysztof Zdziarski 
309266b0663SKrzysztof Zdziarski 	if (accel_dev->u1.vf.irq_enabled) {
310266b0663SKrzysztof Zdziarski 		bus_teardown_intr(pdev,
311266b0663SKrzysztof Zdziarski 				  accel_dev->u1.vf.irq,
312266b0663SKrzysztof Zdziarski 				  accel_dev->u1.vf.cookie);
31378ee8d1cSJulian Grajkowski 		bus_free_resource(pdev, SYS_RES_IRQ, accel_dev->u1.vf.irq);
314266b0663SKrzysztof Zdziarski 	}
31578ee8d1cSJulian Grajkowski 	adf_cleanup_bh(accel_dev);
31678ee8d1cSJulian Grajkowski 	adf_cleanup_pf2vf_bh(accel_dev);
31778ee8d1cSJulian Grajkowski 	adf_disable_msi(accel_dev);
31878ee8d1cSJulian Grajkowski }
31978ee8d1cSJulian Grajkowski 
32078ee8d1cSJulian Grajkowski /**
32178ee8d1cSJulian Grajkowski  * adf_vf_isr_resource_alloc() - Allocate IRQ for acceleration device
32278ee8d1cSJulian Grajkowski  * @accel_dev:  Pointer to acceleration device.
32378ee8d1cSJulian Grajkowski  *
32478ee8d1cSJulian Grajkowski  * Function allocates interrupts for acceleration device virtual function.
32578ee8d1cSJulian Grajkowski  *
32678ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
32778ee8d1cSJulian Grajkowski  */
32878ee8d1cSJulian Grajkowski int
adf_vf_isr_resource_alloc(struct adf_accel_dev * accel_dev)32978ee8d1cSJulian Grajkowski adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
33078ee8d1cSJulian Grajkowski {
33178ee8d1cSJulian Grajkowski 	if (adf_enable_msi(accel_dev))
33278ee8d1cSJulian Grajkowski 		goto err_out;
33378ee8d1cSJulian Grajkowski 
33478ee8d1cSJulian Grajkowski 	if (adf_setup_pf2vf_bh(accel_dev))
335266b0663SKrzysztof Zdziarski 		goto err_disable_msi;
33678ee8d1cSJulian Grajkowski 
33778ee8d1cSJulian Grajkowski 	if (adf_setup_bh(accel_dev))
33878ee8d1cSJulian Grajkowski 		goto err_out;
33978ee8d1cSJulian Grajkowski 
34078ee8d1cSJulian Grajkowski 	if (adf_request_msi_irq(accel_dev))
341266b0663SKrzysztof Zdziarski 		goto err_disable_msi;
34278ee8d1cSJulian Grajkowski 
34378ee8d1cSJulian Grajkowski 	return 0;
344266b0663SKrzysztof Zdziarski 
345266b0663SKrzysztof Zdziarski err_disable_msi:
346266b0663SKrzysztof Zdziarski 	adf_disable_msi(accel_dev);
347266b0663SKrzysztof Zdziarski 
34878ee8d1cSJulian Grajkowski err_out:
349266b0663SKrzysztof Zdziarski 	return -EFAULT;
35078ee8d1cSJulian Grajkowski }
35178ee8d1cSJulian Grajkowski 
35278ee8d1cSJulian Grajkowski /**
35378ee8d1cSJulian Grajkowski  * adf_flush_vf_wq() - Flush workqueue for VF
354266b0663SKrzysztof Zdziarski  * @accel_dev:  Pointer to acceleration device.
35578ee8d1cSJulian Grajkowski  *
356266b0663SKrzysztof Zdziarski  * Function disables the PF/VF interrupts on the VF so that no new messages
357266b0663SKrzysztof Zdziarski  * are received and flushes the workqueue 'adf_vf_stop_wq'.
35878ee8d1cSJulian Grajkowski  *
35978ee8d1cSJulian Grajkowski  * Return: void.
36078ee8d1cSJulian Grajkowski  */
36178ee8d1cSJulian Grajkowski void
adf_flush_vf_wq(struct adf_accel_dev * accel_dev)362266b0663SKrzysztof Zdziarski adf_flush_vf_wq(struct adf_accel_dev *accel_dev)
36378ee8d1cSJulian Grajkowski {
364266b0663SKrzysztof Zdziarski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
365266b0663SKrzysztof Zdziarski 
366266b0663SKrzysztof Zdziarski 	hw_data->disable_pf2vf_interrupt(accel_dev);
367266b0663SKrzysztof Zdziarski 
36878ee8d1cSJulian Grajkowski 	if (adf_vf_stop_wq)
36978ee8d1cSJulian Grajkowski 		flush_workqueue(adf_vf_stop_wq);
37078ee8d1cSJulian Grajkowski }
37178ee8d1cSJulian Grajkowski 
37278ee8d1cSJulian Grajkowski /**
37378ee8d1cSJulian Grajkowski  * adf_init_vf_wq() - Init workqueue for VF
37478ee8d1cSJulian Grajkowski  *
37578ee8d1cSJulian Grajkowski  * Function init workqueue 'adf_vf_stop_wq' for VF.
37678ee8d1cSJulian Grajkowski  *
37778ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
37878ee8d1cSJulian Grajkowski  */
37978ee8d1cSJulian Grajkowski int
adf_init_vf_wq(void)38078ee8d1cSJulian Grajkowski adf_init_vf_wq(void)
38178ee8d1cSJulian Grajkowski {
38278ee8d1cSJulian Grajkowski 	int ret = 0;
38378ee8d1cSJulian Grajkowski 
38478ee8d1cSJulian Grajkowski 	mutex_lock(&vf_stop_wq_lock);
38578ee8d1cSJulian Grajkowski 	if (!adf_vf_stop_wq)
38678ee8d1cSJulian Grajkowski 		adf_vf_stop_wq =
38778ee8d1cSJulian Grajkowski 		    alloc_workqueue("adf_vf_stop_wq", WQ_MEM_RECLAIM, 0);
38878ee8d1cSJulian Grajkowski 
38978ee8d1cSJulian Grajkowski 	if (!adf_vf_stop_wq)
39078ee8d1cSJulian Grajkowski 		ret = ENOMEM;
39178ee8d1cSJulian Grajkowski 
39278ee8d1cSJulian Grajkowski 	mutex_unlock(&vf_stop_wq_lock);
39378ee8d1cSJulian Grajkowski 	return ret;
39478ee8d1cSJulian Grajkowski }
39578ee8d1cSJulian Grajkowski 
39678ee8d1cSJulian Grajkowski void
adf_exit_vf_wq(void)39778ee8d1cSJulian Grajkowski adf_exit_vf_wq(void)
39878ee8d1cSJulian Grajkowski {
399266b0663SKrzysztof Zdziarski 	if (adf_vf_stop_wq)
40078ee8d1cSJulian Grajkowski 		destroy_workqueue(adf_vf_stop_wq);
401266b0663SKrzysztof Zdziarski 
40278ee8d1cSJulian Grajkowski 	adf_vf_stop_wq = NULL;
40378ee8d1cSJulian Grajkowski }
404