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