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