17afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk/*
27afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  This file is provided under a dual BSD/GPLv2 license.  When using or
37afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  redistributing this file, you may do so under either license.
47afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
57afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  GPL LICENSE SUMMARY
67afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  Copyright(c) 2014 Intel Corporation.
77afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  This program is free software; you can redistribute it and/or modify
87afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  it under the terms of version 2 of the GNU General Public License as
97afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  published by the Free Software Foundation.
107afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
117afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  This program is distributed in the hope that it will be useful, but
127afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  WITHOUT ANY WARRANTY; without even the implied warranty of
137afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  General Public License for more details.
157afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
167afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  Contact Information:
177afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  qat-linux@intel.com
187afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
197afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  BSD LICENSE
207afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  Copyright(c) 2014 Intel Corporation.
217afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  Redistribution and use in source and binary forms, with or without
227afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  modification, are permitted provided that the following conditions
237afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  are met:
247afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
257afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk    * Redistributions of source code must retain the above copyright
267afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk      notice, this list of conditions and the following disclaimer.
277afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk    * Redistributions in binary form must reproduce the above copyright
287afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk      notice, this list of conditions and the following disclaimer in
297afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk      the documentation and/or other materials provided with the
307afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk      distribution.
317afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk    * Neither the name of Intel Corporation nor the names of its
327afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk      contributors may be used to endorse or promote products derived
337afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk      from this software without specific prior written permission.
347afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
357afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
367afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
377afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
387afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
397afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
407afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
417afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
427afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
437afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
447afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
457afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
467afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk*/
477afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/kernel.h>
487afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/init.h>
497afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/types.h>
507afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/pci.h>
517afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/slab.h>
527afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/errno.h>
537afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <linux/interrupt.h>
547afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_accel_devices.h>
557afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_common_drv.h>
567afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_cfg.h>
577afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_cfg_strings.h>
587afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_cfg_common.h>
597afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_transport_access_macros.h>
607afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include <adf_transport_internal.h>
617afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk#include "adf_drv.h"
627afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
637afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic int adf_enable_msix(struct adf_accel_dev *accel_dev)
647afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
657afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
667afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
677afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	uint32_t msix_num_entries = hw_data->num_banks + 1;
687afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int i;
697afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
707afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < msix_num_entries; i++)
717afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		pci_dev_info->msix_entries.entries[i].entry = i;
727afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
7351269ad2880774e7d46fb1e0edb7a83e15d05d33Alexander Gordeev	if (pci_enable_msix_exact(pci_dev_info->pci_dev,
7451269ad2880774e7d46fb1e0edb7a83e15d05d33Alexander Gordeev				  pci_dev_info->msix_entries.entries,
7551269ad2880774e7d46fb1e0edb7a83e15d05d33Alexander Gordeev				  msix_num_entries)) {
767afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		pr_err("QAT: Failed to enable MSIX IRQ\n");
777afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		return -EFAULT;
787afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
797afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return 0;
807afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
817afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
827afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic void adf_disable_msix(struct adf_accel_pci *pci_dev_info)
837afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
847afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	pci_disable_msix(pci_dev_info->pci_dev);
857afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
867afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
877afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic irqreturn_t adf_msix_isr_bundle(int irq, void *bank_ptr)
887afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
897afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_etr_bank_data *bank = bank_ptr;
907afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
917afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number, 0);
927752759d957a84c889556e3096db21ec43312eb3Tadeusz Struk	tasklet_hi_schedule(&bank->resp_handler);
937afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return IRQ_HANDLED;
947afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
957afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
967afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
977afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
987afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_accel_dev *accel_dev = dev_ptr;
997afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1007afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	pr_info("QAT: qat_dev%d spurious AE interrupt\n", accel_dev->accel_id);
1017afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return IRQ_HANDLED;
1027afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
1037afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1047afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic int adf_request_irqs(struct adf_accel_dev *accel_dev)
1057afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
1067afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
1077afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
1087afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
1097afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_etr_data *etr_data = accel_dev->transport;
1107afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int ret, i;
1117afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	char *name;
1127afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1137afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	/* Request msix irq for all banks */
1147afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < hw_data->num_banks; i++) {
1157afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		struct adf_etr_bank_data *bank = &etr_data->banks[i];
1167afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		unsigned int cpu, cpus = num_online_cpus();
1177afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1187afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		name = *(pci_dev_info->msix_entries.names + i);
1197afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
1207afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			 "qat%d-bundle%d", accel_dev->accel_id, i);
1217afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		ret = request_irq(msixe[i].vector,
1227afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk				  adf_msix_isr_bundle, 0, name, bank);
1237afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		if (ret) {
1247afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			pr_err("QAT: failed to enable irq %d for %s\n",
1257afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			       msixe[i].vector, name);
1267afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			return ret;
1277afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		}
1287afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1297afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		cpu = ((accel_dev->accel_id * hw_data->num_banks) + i) % cpus;
1307afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		irq_set_affinity_hint(msixe[i].vector, get_cpu_mask(cpu));
1317afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
1327afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1337afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	/* Request msix irq for AE */
1347afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	name = *(pci_dev_info->msix_entries.names + i);
1357afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
1367afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		 "qat%d-ae-cluster", accel_dev->accel_id);
1377afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	ret = request_irq(msixe[i].vector, adf_msix_isr_ae, 0, name, accel_dev);
1387afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (ret) {
1397afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		pr_err("QAT: failed to enable irq %d, for %s\n",
1407afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		       msixe[i].vector, name);
1417afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		return ret;
1427afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
1437afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return ret;
1447afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
1457afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1467afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic void adf_free_irqs(struct adf_accel_dev *accel_dev)
1477afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
1487afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
1497afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
1507afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
1517afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_etr_data *etr_data = accel_dev->transport;
1527afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int i;
1537afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1547afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < hw_data->num_banks; i++) {
1557afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		irq_set_affinity_hint(msixe[i].vector, NULL);
1567afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		free_irq(msixe[i].vector, &etr_data->banks[i]);
1577afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
1587afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	irq_set_affinity_hint(msixe[i].vector, NULL);
1597afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	free_irq(msixe[i].vector, accel_dev);
1607afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
1617afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1627afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
1637afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
1647afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int i;
1657afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	char **names;
1667afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct msix_entry *entries;
1677afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
1687afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	uint32_t msix_num_entries = hw_data->num_banks + 1;
1697afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1707afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	entries = kzalloc_node(msix_num_entries * sizeof(*entries),
17109adc8789c4e895d7548fa9eb5d24ad9a5d91c5dTadeusz Struk			       GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev)));
1727afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (!entries)
1737afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		return -ENOMEM;
1747afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
175d65071ecde1ed1b99d057a877e0e3d29748c3a4dTadeusz Struk	names = kcalloc(msix_num_entries, sizeof(char *), GFP_KERNEL);
1767afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (!names) {
1777afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		kfree(entries);
1787afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		return -ENOMEM;
1797afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
1807afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < msix_num_entries; i++) {
1817afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		*(names + i) = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
1827afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		if (!(*(names + i)))
1837afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			goto err;
1847afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
1857afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	accel_dev->accel_pci_dev.msix_entries.entries = entries;
1867afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	accel_dev->accel_pci_dev.msix_entries.names = names;
1877afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return 0;
1887afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukerr:
1897afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < msix_num_entries; i++) {
1907afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		if (*(names + i))
1917afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			kfree(*(names + i));
1927afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
1937afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	kfree(entries);
1947afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	kfree(names);
1957afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return -ENOMEM;
1967afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
1977afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
1987afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic void adf_isr_free_msix_entry_table(struct adf_accel_dev *accel_dev)
1997afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
2007afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
2017afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	uint32_t msix_num_entries = hw_data->num_banks + 1;
2027afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	char **names = accel_dev->accel_pci_dev.msix_entries.names;
2037afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int i;
2047afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2057afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	kfree(accel_dev->accel_pci_dev.msix_entries.entries);
2067afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < msix_num_entries; i++) {
2077afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		if (*(names + i))
2087afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			kfree(*(names + i));
2097afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
2107afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	kfree(names);
2117afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
2127afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2137afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic int adf_setup_bh(struct adf_accel_dev *accel_dev)
2147afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
2157afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_etr_data *priv_data = accel_dev->transport;
2167afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
2177afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int i;
2187afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2197afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < hw_data->num_banks; i++)
2207752759d957a84c889556e3096db21ec43312eb3Tadeusz Struk		tasklet_init(&priv_data->banks[i].resp_handler,
2217afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			     adf_response_handler,
2227afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk			     (unsigned long)&priv_data->banks[i]);
2237afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return 0;
2247afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
2257afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2267afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukstatic void adf_cleanup_bh(struct adf_accel_dev *accel_dev)
2277afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
2287afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_etr_data *priv_data = accel_dev->transport;
2297afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
2307afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int i;
2317afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2327afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	for (i = 0; i < hw_data->num_banks; i++) {
2337752759d957a84c889556e3096db21ec43312eb3Tadeusz Struk		tasklet_disable(&priv_data->banks[i].resp_handler);
2347752759d957a84c889556e3096db21ec43312eb3Tadeusz Struk		tasklet_kill(&priv_data->banks[i].resp_handler);
2357afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	}
2367afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
2377afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2387afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukvoid adf_isr_resource_free(struct adf_accel_dev *accel_dev)
2397afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
2407afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	adf_free_irqs(accel_dev);
2417afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	adf_cleanup_bh(accel_dev);
2427afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	adf_disable_msix(&accel_dev->accel_pci_dev);
2437afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	adf_isr_free_msix_entry_table(accel_dev);
2447afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
2457afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2467afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukint adf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
2477afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk{
2487afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	int ret;
2497afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2507afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	ret = adf_isr_alloc_msix_entry_table(accel_dev);
2517afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (ret)
2527afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		return ret;
2537afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (adf_enable_msix(accel_dev))
2547afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		goto err_out;
2557afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2567afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (adf_setup_bh(accel_dev))
2577afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		goto err_out;
2587afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2597afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	if (adf_request_irqs(accel_dev))
2607afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk		goto err_out;
2617afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk
2627afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return 0;
2637afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Strukerr_out:
2647afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	adf_isr_resource_free(accel_dev);
2657afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk	return -EFAULT;
2667afa232e76ced910a191a3f6669d8f48bcb46b3eTadeusz Struk}
267