xref: /freebsd-src/sys/dev/qat/qat_common/adf_init.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
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 "adf_cfg.h"
578ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
678ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
778ee8d1cSJulian Grajkowski #include "icp_qat_uclo.h"
878ee8d1cSJulian Grajkowski #include "icp_qat_fw.h"
978ee8d1cSJulian Grajkowski #include "icp_qat_fw_init_admin.h"
1078ee8d1cSJulian Grajkowski #include "adf_cfg_strings.h"
1178ee8d1cSJulian Grajkowski #include "adf_dev_err.h"
12*266b0663SKrzysztof Zdziarski #include "adf_uio.h"
1378ee8d1cSJulian Grajkowski #include "adf_transport_access_macros.h"
1478ee8d1cSJulian Grajkowski #include "adf_transport_internal.h"
1578ee8d1cSJulian Grajkowski #include <sys/mutex.h>
1678ee8d1cSJulian Grajkowski #include <linux/delay.h>
1778ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
1878ee8d1cSJulian Grajkowski #include "adf_cfg.h"
1978ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
2078ee8d1cSJulian Grajkowski #include "icp_qat_fw.h"
2178ee8d1cSJulian Grajkowski 
2278ee8d1cSJulian Grajkowski /* Mask used to check the CompressAndVerify capability bit */
2378ee8d1cSJulian Grajkowski #define DC_CNV_EXTENDED_CAPABILITY (0x01)
2478ee8d1cSJulian Grajkowski 
2578ee8d1cSJulian Grajkowski /* Mask used to check the CompressAndVerifyAndRecover capability bit */
2678ee8d1cSJulian Grajkowski #define DC_CNVNR_EXTENDED_CAPABILITY (0x100)
2778ee8d1cSJulian Grajkowski 
2878ee8d1cSJulian Grajkowski static LIST_HEAD(service_table);
2978ee8d1cSJulian Grajkowski static DEFINE_MUTEX(service_lock);
3078ee8d1cSJulian Grajkowski 
3178ee8d1cSJulian Grajkowski static void
adf_service_add(struct service_hndl * service)3278ee8d1cSJulian Grajkowski adf_service_add(struct service_hndl *service)
3378ee8d1cSJulian Grajkowski {
3478ee8d1cSJulian Grajkowski 	mutex_lock(&service_lock);
3578ee8d1cSJulian Grajkowski 	list_add(&service->list, &service_table);
3678ee8d1cSJulian Grajkowski 	mutex_unlock(&service_lock);
3778ee8d1cSJulian Grajkowski }
3878ee8d1cSJulian Grajkowski 
3978ee8d1cSJulian Grajkowski int
adf_service_register(struct service_hndl * service)4078ee8d1cSJulian Grajkowski adf_service_register(struct service_hndl *service)
4178ee8d1cSJulian Grajkowski {
4278ee8d1cSJulian Grajkowski 	memset(service->init_status, 0, sizeof(service->init_status));
4378ee8d1cSJulian Grajkowski 	memset(service->start_status, 0, sizeof(service->start_status));
4478ee8d1cSJulian Grajkowski 	adf_service_add(service);
4578ee8d1cSJulian Grajkowski 	return 0;
4678ee8d1cSJulian Grajkowski }
4778ee8d1cSJulian Grajkowski 
4878ee8d1cSJulian Grajkowski static void
adf_service_remove(struct service_hndl * service)4978ee8d1cSJulian Grajkowski adf_service_remove(struct service_hndl *service)
5078ee8d1cSJulian Grajkowski {
5178ee8d1cSJulian Grajkowski 	mutex_lock(&service_lock);
5278ee8d1cSJulian Grajkowski 	list_del(&service->list);
5378ee8d1cSJulian Grajkowski 	mutex_unlock(&service_lock);
5478ee8d1cSJulian Grajkowski }
5578ee8d1cSJulian Grajkowski 
5678ee8d1cSJulian Grajkowski int
adf_service_unregister(struct service_hndl * service)5778ee8d1cSJulian Grajkowski adf_service_unregister(struct service_hndl *service)
5878ee8d1cSJulian Grajkowski {
5978ee8d1cSJulian Grajkowski 	int i;
6078ee8d1cSJulian Grajkowski 
6178ee8d1cSJulian Grajkowski 	for (i = 0; i < ARRAY_SIZE(service->init_status); i++) {
6278ee8d1cSJulian Grajkowski 		if (service->init_status[i] || service->start_status[i]) {
6378ee8d1cSJulian Grajkowski 			pr_err("QAT: Could not remove active service [%d]\n",
6478ee8d1cSJulian Grajkowski 			       i);
6578ee8d1cSJulian Grajkowski 			return EFAULT;
6678ee8d1cSJulian Grajkowski 		}
6778ee8d1cSJulian Grajkowski 	}
6878ee8d1cSJulian Grajkowski 	adf_service_remove(service);
6978ee8d1cSJulian Grajkowski 	return 0;
7078ee8d1cSJulian Grajkowski }
7178ee8d1cSJulian Grajkowski 
7278ee8d1cSJulian Grajkowski static int
adf_cfg_add_device_params(struct adf_accel_dev * accel_dev)7378ee8d1cSJulian Grajkowski adf_cfg_add_device_params(struct adf_accel_dev *accel_dev)
7478ee8d1cSJulian Grajkowski {
7578ee8d1cSJulian Grajkowski 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
7678ee8d1cSJulian Grajkowski 	char hw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
7778ee8d1cSJulian Grajkowski 	char mmp_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
7878ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = NULL;
7978ee8d1cSJulian Grajkowski 	unsigned long val;
8078ee8d1cSJulian Grajkowski 	if (!accel_dev)
8178ee8d1cSJulian Grajkowski 		return -EINVAL;
8278ee8d1cSJulian Grajkowski 
8378ee8d1cSJulian Grajkowski 	hw_data = accel_dev->hw_device;
8478ee8d1cSJulian Grajkowski 
8578ee8d1cSJulian Grajkowski 	if (adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC))
8678ee8d1cSJulian Grajkowski 		goto err;
8778ee8d1cSJulian Grajkowski 
8878ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_MAX_BANKS);
8978ee8d1cSJulian Grajkowski 	val = GET_MAX_BANKS(accel_dev);
9078ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
9178ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
9278ee8d1cSJulian Grajkowski 		goto err;
9378ee8d1cSJulian Grajkowski 
9478ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_CAPABILITIES_MASK);
9578ee8d1cSJulian Grajkowski 	val = hw_data->accel_capabilities_mask;
9678ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
9778ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)val, ADF_HEX))
9878ee8d1cSJulian Grajkowski 		goto err;
9978ee8d1cSJulian Grajkowski 
10078ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_PKG_ID);
10178ee8d1cSJulian Grajkowski 	val = accel_dev->accel_id;
10278ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
10378ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
10478ee8d1cSJulian Grajkowski 		goto err;
10578ee8d1cSJulian Grajkowski 
10678ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_NODE_ID);
10778ee8d1cSJulian Grajkowski 	val = dev_to_node(GET_DEV(accel_dev));
10878ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
10978ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
11078ee8d1cSJulian Grajkowski 		goto err;
11178ee8d1cSJulian Grajkowski 
11278ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_MAX_RINGS_PER_BANK);
11378ee8d1cSJulian Grajkowski 	val = hw_data->num_rings_per_bank;
11478ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
11578ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
11678ee8d1cSJulian Grajkowski 		goto err;
11778ee8d1cSJulian Grajkowski 
11878ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_HW_REV_ID_KEY);
11978ee8d1cSJulian Grajkowski 	snprintf(hw_version,
12078ee8d1cSJulian Grajkowski 		 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
12178ee8d1cSJulian Grajkowski 		 "%d",
12278ee8d1cSJulian Grajkowski 		 accel_dev->accel_pci_dev.revid);
12378ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
12478ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)hw_version, ADF_STR))
12578ee8d1cSJulian Grajkowski 		goto err;
12678ee8d1cSJulian Grajkowski 
12778ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_MMP_VER_KEY);
12878ee8d1cSJulian Grajkowski 	snprintf(mmp_version,
12978ee8d1cSJulian Grajkowski 		 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
13078ee8d1cSJulian Grajkowski 		 "%d.%d.%d",
13178ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.mmp_version_major,
13278ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.mmp_version_minor,
13378ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.mmp_version_patch);
13478ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
13578ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)mmp_version, ADF_STR))
13678ee8d1cSJulian Grajkowski 		goto err;
13778ee8d1cSJulian Grajkowski 
13878ee8d1cSJulian Grajkowski 	return 0;
13978ee8d1cSJulian Grajkowski err:
14078ee8d1cSJulian Grajkowski 	device_printf(GET_DEV(accel_dev),
14178ee8d1cSJulian Grajkowski 		      "Failed to add internal values to accel_dev cfg\n");
14278ee8d1cSJulian Grajkowski 	return -EINVAL;
14378ee8d1cSJulian Grajkowski }
14478ee8d1cSJulian Grajkowski 
14578ee8d1cSJulian Grajkowski static int
adf_cfg_add_fw_version(struct adf_accel_dev * accel_dev)14678ee8d1cSJulian Grajkowski adf_cfg_add_fw_version(struct adf_accel_dev *accel_dev)
14778ee8d1cSJulian Grajkowski {
14878ee8d1cSJulian Grajkowski 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
14978ee8d1cSJulian Grajkowski 	char fw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
15078ee8d1cSJulian Grajkowski 
15178ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_UOF_VER_KEY);
15278ee8d1cSJulian Grajkowski 	snprintf(fw_version,
15378ee8d1cSJulian Grajkowski 		 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
15478ee8d1cSJulian Grajkowski 		 "%d.%d.%d",
15578ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.fw_version_major,
15678ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.fw_version_minor,
15778ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.fw_version_patch);
15878ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
15978ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)fw_version, ADF_STR))
16078ee8d1cSJulian Grajkowski 		return EFAULT;
16178ee8d1cSJulian Grajkowski 
16278ee8d1cSJulian Grajkowski 	return 0;
16378ee8d1cSJulian Grajkowski }
16478ee8d1cSJulian Grajkowski 
16578ee8d1cSJulian Grajkowski static int
adf_cfg_add_ext_params(struct adf_accel_dev * accel_dev)16678ee8d1cSJulian Grajkowski adf_cfg_add_ext_params(struct adf_accel_dev *accel_dev)
16778ee8d1cSJulian Grajkowski {
16878ee8d1cSJulian Grajkowski 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
16978ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
17078ee8d1cSJulian Grajkowski 	unsigned long val;
17178ee8d1cSJulian Grajkowski 
17278ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DC_EXTENDED_FEATURES);
17378ee8d1cSJulian Grajkowski 
17478ee8d1cSJulian Grajkowski 	val = hw_data->extended_dc_capabilities;
17578ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
17678ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)val, ADF_HEX))
17778ee8d1cSJulian Grajkowski 		return -EINVAL;
17878ee8d1cSJulian Grajkowski 
17978ee8d1cSJulian Grajkowski 	return 0;
18078ee8d1cSJulian Grajkowski }
18178ee8d1cSJulian Grajkowski 
18278ee8d1cSJulian Grajkowski void
adf_error_notifier(uintptr_t arg)18378ee8d1cSJulian Grajkowski adf_error_notifier(uintptr_t arg)
18478ee8d1cSJulian Grajkowski {
18578ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = (struct adf_accel_dev *)arg;
18678ee8d1cSJulian Grajkowski 	struct service_hndl *service;
18778ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
18878ee8d1cSJulian Grajkowski 
18978ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
19078ee8d1cSJulian Grajkowski 	{
19178ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
19278ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_ERROR))
19378ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
19478ee8d1cSJulian Grajkowski 				      "Failed to send error event to %s.\n",
19578ee8d1cSJulian Grajkowski 				      service->name);
19678ee8d1cSJulian Grajkowski 	}
19778ee8d1cSJulian Grajkowski }
19878ee8d1cSJulian Grajkowski 
19978ee8d1cSJulian Grajkowski /**
20078ee8d1cSJulian Grajkowski  * adf_set_ssm_wdtimer() - Initialize the slice hang watchdog timer.
20178ee8d1cSJulian Grajkowski  *
20278ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
20378ee8d1cSJulian Grajkowski  */
20478ee8d1cSJulian Grajkowski int
adf_set_ssm_wdtimer(struct adf_accel_dev * accel_dev)20578ee8d1cSJulian Grajkowski adf_set_ssm_wdtimer(struct adf_accel_dev *accel_dev)
20678ee8d1cSJulian Grajkowski {
20778ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
20878ee8d1cSJulian Grajkowski 	struct adf_bar *misc_bar =
20978ee8d1cSJulian Grajkowski 	    &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
21078ee8d1cSJulian Grajkowski 	struct resource *csr = misc_bar->virt_addr;
21178ee8d1cSJulian Grajkowski 	u32 i;
21278ee8d1cSJulian Grajkowski 	unsigned int mask;
21378ee8d1cSJulian Grajkowski 	u32 clk_per_sec = hw_data->get_clock_speed(hw_data);
21478ee8d1cSJulian Grajkowski 	u32 timer_val = ADF_WDT_TIMER_SYM_COMP_MS * (clk_per_sec / 1000);
215a977168cSMichal Gulbicki 	u32 timer_val_pke = ADF_GEN2_SSM_WDT_PKE_DEFAULT_VALUE;
21678ee8d1cSJulian Grajkowski 	char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
21778ee8d1cSJulian Grajkowski 
21878ee8d1cSJulian Grajkowski 	/* Get Watch Dog Timer for CySym+Comp from the configuration */
21978ee8d1cSJulian Grajkowski 	if (!adf_cfg_get_param_value(accel_dev,
22078ee8d1cSJulian Grajkowski 				     ADF_GENERAL_SEC,
22178ee8d1cSJulian Grajkowski 				     ADF_DEV_SSM_WDT_BULK,
22278ee8d1cSJulian Grajkowski 				     (char *)timer_str)) {
22378ee8d1cSJulian Grajkowski 		if (!compat_strtouint((char *)timer_str,
22478ee8d1cSJulian Grajkowski 				      ADF_CFG_BASE_DEC,
22578ee8d1cSJulian Grajkowski 				      &timer_val))
22678ee8d1cSJulian Grajkowski 			/* Convert msec to CPP clocks */
22778ee8d1cSJulian Grajkowski 			timer_val = timer_val * (clk_per_sec / 1000);
22878ee8d1cSJulian Grajkowski 	}
22978ee8d1cSJulian Grajkowski 	/* Get Watch Dog Timer for CyAsym from the configuration */
23078ee8d1cSJulian Grajkowski 	if (!adf_cfg_get_param_value(accel_dev,
23178ee8d1cSJulian Grajkowski 				     ADF_GENERAL_SEC,
23278ee8d1cSJulian Grajkowski 				     ADF_DEV_SSM_WDT_PKE,
23378ee8d1cSJulian Grajkowski 				     (char *)timer_str)) {
23478ee8d1cSJulian Grajkowski 		if (!compat_strtouint((char *)timer_str,
23578ee8d1cSJulian Grajkowski 				      ADF_CFG_BASE_DEC,
23678ee8d1cSJulian Grajkowski 				      &timer_val_pke))
23778ee8d1cSJulian Grajkowski 			/* Convert msec to CPP clocks */
23878ee8d1cSJulian Grajkowski 			timer_val_pke = timer_val_pke * (clk_per_sec / 1000);
23978ee8d1cSJulian Grajkowski 	}
24078ee8d1cSJulian Grajkowski 
24178ee8d1cSJulian Grajkowski 	for (i = 0, mask = hw_data->accel_mask; mask; i++, mask >>= 1) {
24278ee8d1cSJulian Grajkowski 		if (!(mask & 1))
24378ee8d1cSJulian Grajkowski 			continue;
24478ee8d1cSJulian Grajkowski 		/* Enable Watch Dog Timer for CySym + Comp */
24578ee8d1cSJulian Grajkowski 		ADF_CSR_WR(csr, ADF_SSMWDT(i), timer_val);
24678ee8d1cSJulian Grajkowski 		/* Enable Watch Dog Timer for CyAsym */
24778ee8d1cSJulian Grajkowski 		ADF_CSR_WR(csr, ADF_SSMWDTPKE(i), timer_val_pke);
24878ee8d1cSJulian Grajkowski 	}
24978ee8d1cSJulian Grajkowski 	return 0;
25078ee8d1cSJulian Grajkowski }
25178ee8d1cSJulian Grajkowski 
25278ee8d1cSJulian Grajkowski /**
25378ee8d1cSJulian Grajkowski  * adf_dev_init() - Init data structures and services for the given accel device
25478ee8d1cSJulian Grajkowski  * @accel_dev: Pointer to acceleration device.
25578ee8d1cSJulian Grajkowski  *
25678ee8d1cSJulian Grajkowski  * Initialize the ring data structures and the admin comms and arbitration
25778ee8d1cSJulian Grajkowski  * services.
25878ee8d1cSJulian Grajkowski  *
25978ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
26078ee8d1cSJulian Grajkowski  */
26178ee8d1cSJulian Grajkowski int
adf_dev_init(struct adf_accel_dev * accel_dev)26278ee8d1cSJulian Grajkowski adf_dev_init(struct adf_accel_dev *accel_dev)
26378ee8d1cSJulian Grajkowski {
26478ee8d1cSJulian Grajkowski 	struct service_hndl *service;
26578ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
26678ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
26778ee8d1cSJulian Grajkowski 	char value[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
26878ee8d1cSJulian Grajkowski 	int ret = 0;
26978ee8d1cSJulian Grajkowski 	sysctl_ctx_init(&accel_dev->sysctl_ctx);
27078ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, &accel_dev->status);
27178ee8d1cSJulian Grajkowski 
27278ee8d1cSJulian Grajkowski 	if (!hw_data) {
27378ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
27478ee8d1cSJulian Grajkowski 			      "Failed to init device - hw_data not set\n");
27578ee8d1cSJulian Grajkowski 		return EFAULT;
27678ee8d1cSJulian Grajkowski 	}
27778ee8d1cSJulian Grajkowski 	if (hw_data->reset_hw_units)
27878ee8d1cSJulian Grajkowski 		hw_data->reset_hw_units(accel_dev);
27978ee8d1cSJulian Grajkowski 
28078ee8d1cSJulian Grajkowski 	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status) &&
28178ee8d1cSJulian Grajkowski 	    !accel_dev->is_vf) {
28278ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Device not configured\n");
28378ee8d1cSJulian Grajkowski 		return EFAULT;
28478ee8d1cSJulian Grajkowski 	}
28578ee8d1cSJulian Grajkowski 
28678ee8d1cSJulian Grajkowski 	if (adf_init_etr_data(accel_dev)) {
28778ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Failed initialize etr\n");
28878ee8d1cSJulian Grajkowski 		return EFAULT;
28978ee8d1cSJulian Grajkowski 	}
29078ee8d1cSJulian Grajkowski 
291a977168cSMichal Gulbicki 	if (hw_data->init_device && hw_data->init_device(accel_dev)) {
292a977168cSMichal Gulbicki 		device_printf(GET_DEV(accel_dev),
293a977168cSMichal Gulbicki 			      "Failed to initialize device\n");
294a977168cSMichal Gulbicki 		return EFAULT;
295a977168cSMichal Gulbicki 	}
296a977168cSMichal Gulbicki 
29778ee8d1cSJulian Grajkowski 	if (hw_data->init_accel_units && hw_data->init_accel_units(accel_dev)) {
29878ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
29978ee8d1cSJulian Grajkowski 			      "Failed initialize accel_units\n");
30078ee8d1cSJulian Grajkowski 		return EFAULT;
30178ee8d1cSJulian Grajkowski 	}
30278ee8d1cSJulian Grajkowski 
30378ee8d1cSJulian Grajkowski 	if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) {
30478ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
30578ee8d1cSJulian Grajkowski 			      "Failed initialize admin comms\n");
30678ee8d1cSJulian Grajkowski 		return EFAULT;
30778ee8d1cSJulian Grajkowski 	}
30878ee8d1cSJulian Grajkowski 
30978ee8d1cSJulian Grajkowski 	if (hw_data->init_arb && hw_data->init_arb(accel_dev)) {
31078ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
31178ee8d1cSJulian Grajkowski 			      "Failed initialize hw arbiter\n");
31278ee8d1cSJulian Grajkowski 		return EFAULT;
31378ee8d1cSJulian Grajkowski 	}
31478ee8d1cSJulian Grajkowski 
31578ee8d1cSJulian Grajkowski 	if (hw_data->set_asym_rings_mask)
31678ee8d1cSJulian Grajkowski 		hw_data->set_asym_rings_mask(accel_dev);
31778ee8d1cSJulian Grajkowski 
31878ee8d1cSJulian Grajkowski 	hw_data->enable_ints(accel_dev);
31978ee8d1cSJulian Grajkowski 
32078ee8d1cSJulian Grajkowski 	if (adf_ae_init(accel_dev)) {
32178ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
32278ee8d1cSJulian Grajkowski 			      "Failed to initialise Acceleration Engine\n");
32378ee8d1cSJulian Grajkowski 		return EFAULT;
32478ee8d1cSJulian Grajkowski 	}
32578ee8d1cSJulian Grajkowski 
32678ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
32778ee8d1cSJulian Grajkowski 
32878ee8d1cSJulian Grajkowski 	if (adf_ae_fw_load(accel_dev)) {
32978ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
33078ee8d1cSJulian Grajkowski 			      "Failed to load acceleration FW\n");
33178ee8d1cSJulian Grajkowski 		return EFAULT;
33278ee8d1cSJulian Grajkowski 	}
33378ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
33478ee8d1cSJulian Grajkowski 
33578ee8d1cSJulian Grajkowski 	if (hw_data->alloc_irq(accel_dev)) {
33678ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
33778ee8d1cSJulian Grajkowski 			      "Failed to allocate interrupts\n");
33878ee8d1cSJulian Grajkowski 		return EFAULT;
33978ee8d1cSJulian Grajkowski 	}
34078ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
34178ee8d1cSJulian Grajkowski 
34278ee8d1cSJulian Grajkowski 	if (hw_data->init_ras && hw_data->init_ras(accel_dev)) {
34378ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Failed to init RAS\n");
34478ee8d1cSJulian Grajkowski 		return EFAULT;
34578ee8d1cSJulian Grajkowski 	}
34678ee8d1cSJulian Grajkowski 
34778ee8d1cSJulian Grajkowski 	hw_data->enable_ints(accel_dev);
34878ee8d1cSJulian Grajkowski 
34978ee8d1cSJulian Grajkowski 	hw_data->enable_error_correction(accel_dev);
35078ee8d1cSJulian Grajkowski 
351*266b0663SKrzysztof Zdziarski 	ret = hw_data->csr_info.pfvf_ops.enable_comms(accel_dev);
352*266b0663SKrzysztof Zdziarski 	if (ret)
353*266b0663SKrzysztof Zdziarski 		return ret;
35478ee8d1cSJulian Grajkowski 
35578ee8d1cSJulian Grajkowski 	if (adf_cfg_add_device_params(accel_dev))
35678ee8d1cSJulian Grajkowski 		return EFAULT;
35778ee8d1cSJulian Grajkowski 
35878ee8d1cSJulian Grajkowski 	if (hw_data->add_pke_stats && hw_data->add_pke_stats(accel_dev))
35978ee8d1cSJulian Grajkowski 		return EFAULT;
36078ee8d1cSJulian Grajkowski 
36178ee8d1cSJulian Grajkowski 	if (hw_data->add_misc_error && hw_data->add_misc_error(accel_dev))
36278ee8d1cSJulian Grajkowski 		return EFAULT;
36378ee8d1cSJulian Grajkowski 	/*
36478ee8d1cSJulian Grajkowski 	 * Subservice initialisation is divided into two stages: init and start.
36578ee8d1cSJulian Grajkowski 	 * This is to facilitate any ordering dependencies between services
36678ee8d1cSJulian Grajkowski 	 * prior to starting any of the accelerators.
36778ee8d1cSJulian Grajkowski 	 */
36878ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
36978ee8d1cSJulian Grajkowski 	{
37078ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
37178ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
37278ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
37378ee8d1cSJulian Grajkowski 				      "Failed to initialise service %s\n",
37478ee8d1cSJulian Grajkowski 				      service->name);
37578ee8d1cSJulian Grajkowski 			return EFAULT;
37678ee8d1cSJulian Grajkowski 		}
37778ee8d1cSJulian Grajkowski 		set_bit(accel_dev->accel_id, service->init_status);
37878ee8d1cSJulian Grajkowski 	}
37978ee8d1cSJulian Grajkowski 
38078ee8d1cSJulian Grajkowski 	/* Read autoreset on error parameter */
38178ee8d1cSJulian Grajkowski 	ret = adf_cfg_get_param_value(accel_dev,
38278ee8d1cSJulian Grajkowski 				      ADF_GENERAL_SEC,
38378ee8d1cSJulian Grajkowski 				      ADF_AUTO_RESET_ON_ERROR,
38478ee8d1cSJulian Grajkowski 				      value);
38578ee8d1cSJulian Grajkowski 	if (!ret) {
38678ee8d1cSJulian Grajkowski 		if (compat_strtouint(value,
38778ee8d1cSJulian Grajkowski 				     10,
38878ee8d1cSJulian Grajkowski 				     &accel_dev->autoreset_on_error)) {
38978ee8d1cSJulian Grajkowski 			device_printf(
39078ee8d1cSJulian Grajkowski 			    GET_DEV(accel_dev),
39178ee8d1cSJulian Grajkowski 			    "Failed converting %s to a decimal value\n",
39278ee8d1cSJulian Grajkowski 			    ADF_AUTO_RESET_ON_ERROR);
39378ee8d1cSJulian Grajkowski 			return EFAULT;
39478ee8d1cSJulian Grajkowski 		}
39578ee8d1cSJulian Grajkowski 	}
39678ee8d1cSJulian Grajkowski 
39778ee8d1cSJulian Grajkowski 	return 0;
39878ee8d1cSJulian Grajkowski }
39978ee8d1cSJulian Grajkowski 
40078ee8d1cSJulian Grajkowski /**
40178ee8d1cSJulian Grajkowski  * adf_dev_start() - Start acceleration service for the given accel device
40278ee8d1cSJulian Grajkowski  * @accel_dev:    Pointer to acceleration device.
40378ee8d1cSJulian Grajkowski  *
40478ee8d1cSJulian Grajkowski  * Function notifies all the registered services that the acceleration device
40578ee8d1cSJulian Grajkowski  * is ready to be used.
40678ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
40778ee8d1cSJulian Grajkowski  *
40878ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
40978ee8d1cSJulian Grajkowski  */
41078ee8d1cSJulian Grajkowski int
adf_dev_start(struct adf_accel_dev * accel_dev)41178ee8d1cSJulian Grajkowski adf_dev_start(struct adf_accel_dev *accel_dev)
41278ee8d1cSJulian Grajkowski {
41378ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
41478ee8d1cSJulian Grajkowski 	struct service_hndl *service;
41578ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
41678ee8d1cSJulian Grajkowski 
41778ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_STARTING, &accel_dev->status);
41878ee8d1cSJulian Grajkowski 	if (adf_devmgr_verify_id(&accel_dev->accel_id)) {
41978ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
42078ee8d1cSJulian Grajkowski 			      "QAT: Device %d not found\n",
42178ee8d1cSJulian Grajkowski 			      accel_dev->accel_id);
42278ee8d1cSJulian Grajkowski 		return ENODEV;
42378ee8d1cSJulian Grajkowski 	}
42478ee8d1cSJulian Grajkowski 	if (adf_ae_start(accel_dev)) {
42578ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "AE Start Failed\n");
42678ee8d1cSJulian Grajkowski 		return EFAULT;
42778ee8d1cSJulian Grajkowski 	}
42878ee8d1cSJulian Grajkowski 
42978ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
43078ee8d1cSJulian Grajkowski 	if (hw_data->send_admin_init(accel_dev)) {
43178ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
43278ee8d1cSJulian Grajkowski 			      "Failed to send init message\n");
43378ee8d1cSJulian Grajkowski 		return EFAULT;
43478ee8d1cSJulian Grajkowski 	}
43578ee8d1cSJulian Grajkowski 
43678ee8d1cSJulian Grajkowski 	if (adf_cfg_add_fw_version(accel_dev)) {
43778ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
43878ee8d1cSJulian Grajkowski 			      "Failed to update configuration FW version\n");
43978ee8d1cSJulian Grajkowski 		return EFAULT;
44078ee8d1cSJulian Grajkowski 	}
44178ee8d1cSJulian Grajkowski 
44278ee8d1cSJulian Grajkowski 	if (hw_data->measure_clock)
44378ee8d1cSJulian Grajkowski 		hw_data->measure_clock(accel_dev);
44478ee8d1cSJulian Grajkowski 
44578ee8d1cSJulian Grajkowski 	/*
44678ee8d1cSJulian Grajkowski 	 * Set ssm watch dog timer for slice hang detection
44778ee8d1cSJulian Grajkowski 	 * Note! Not supported on devices older than C62x
44878ee8d1cSJulian Grajkowski 	 */
44978ee8d1cSJulian Grajkowski 	if (hw_data->set_ssm_wdtimer && hw_data->set_ssm_wdtimer(accel_dev)) {
45078ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
45178ee8d1cSJulian Grajkowski 			      "QAT: Failed to set ssm watch dog timer\n");
45278ee8d1cSJulian Grajkowski 		return EFAULT;
45378ee8d1cSJulian Grajkowski 	}
45478ee8d1cSJulian Grajkowski 
455*266b0663SKrzysztof Zdziarski 	if (hw_data->int_timer_init && hw_data->int_timer_init(accel_dev)) {
456*266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
457*266b0663SKrzysztof Zdziarski 			      "Failed to init heartbeat interrupt timer\n");
458*266b0663SKrzysztof Zdziarski 		return -EFAULT;
459*266b0663SKrzysztof Zdziarski 	}
460*266b0663SKrzysztof Zdziarski 
46178ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
46278ee8d1cSJulian Grajkowski 	{
46378ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
46478ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_START)) {
46578ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
46678ee8d1cSJulian Grajkowski 				      "Failed to start service %s\n",
46778ee8d1cSJulian Grajkowski 				      service->name);
46878ee8d1cSJulian Grajkowski 			return EFAULT;
46978ee8d1cSJulian Grajkowski 		}
47078ee8d1cSJulian Grajkowski 		set_bit(accel_dev->accel_id, service->start_status);
47178ee8d1cSJulian Grajkowski 	}
47278ee8d1cSJulian Grajkowski 
473*266b0663SKrzysztof Zdziarski 	if (accel_dev->is_vf || !accel_dev->u1.pf.vf_info) {
474*266b0663SKrzysztof Zdziarski 		/*Register UIO devices */
475*266b0663SKrzysztof Zdziarski 		if (adf_uio_register(accel_dev)) {
476*266b0663SKrzysztof Zdziarski 			adf_uio_remove(accel_dev);
477*266b0663SKrzysztof Zdziarski 			device_printf(GET_DEV(accel_dev),
478*266b0663SKrzysztof Zdziarski 				      "Failed to register UIO devices\n");
479*266b0663SKrzysztof Zdziarski 			set_bit(ADF_STATUS_STARTING, &accel_dev->status);
480*266b0663SKrzysztof Zdziarski 			clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
481*266b0663SKrzysztof Zdziarski 			return ENODEV;
482*266b0663SKrzysztof Zdziarski 		}
483*266b0663SKrzysztof Zdziarski 	}
484*266b0663SKrzysztof Zdziarski 
48578ee8d1cSJulian Grajkowski 	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status) &&
48678ee8d1cSJulian Grajkowski 	    adf_cfg_add_ext_params(accel_dev))
48778ee8d1cSJulian Grajkowski 		return EFAULT;
48878ee8d1cSJulian Grajkowski 
48978ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
49078ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_STARTED, &accel_dev->status);
49178ee8d1cSJulian Grajkowski 
49278ee8d1cSJulian Grajkowski 	return 0;
49378ee8d1cSJulian Grajkowski }
49478ee8d1cSJulian Grajkowski 
49578ee8d1cSJulian Grajkowski /**
49678ee8d1cSJulian Grajkowski  * adf_dev_stop() - Stop acceleration service for the given accel device
49778ee8d1cSJulian Grajkowski  * @accel_dev:    Pointer to acceleration device.
49878ee8d1cSJulian Grajkowski  *
49978ee8d1cSJulian Grajkowski  * Function notifies all the registered services that the acceleration device
50078ee8d1cSJulian Grajkowski  * is shuting down.
50178ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
50278ee8d1cSJulian Grajkowski  *
50378ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
50478ee8d1cSJulian Grajkowski  */
50578ee8d1cSJulian Grajkowski int
adf_dev_stop(struct adf_accel_dev * accel_dev)50678ee8d1cSJulian Grajkowski adf_dev_stop(struct adf_accel_dev *accel_dev)
50778ee8d1cSJulian Grajkowski {
50878ee8d1cSJulian Grajkowski 	struct service_hndl *service;
50978ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
51078ee8d1cSJulian Grajkowski 
51178ee8d1cSJulian Grajkowski 	if (adf_devmgr_verify_id(&accel_dev->accel_id)) {
51278ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
51378ee8d1cSJulian Grajkowski 			      "QAT: Device %d not found\n",
51478ee8d1cSJulian Grajkowski 			      accel_dev->accel_id);
51578ee8d1cSJulian Grajkowski 		return ENODEV;
51678ee8d1cSJulian Grajkowski 	}
51778ee8d1cSJulian Grajkowski 	if (!adf_dev_started(accel_dev) &&
51878ee8d1cSJulian Grajkowski 	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) {
51978ee8d1cSJulian Grajkowski 		return 0;
52078ee8d1cSJulian Grajkowski 	}
52178ee8d1cSJulian Grajkowski 
52278ee8d1cSJulian Grajkowski 	if (adf_dev_stop_notify_sync(accel_dev)) {
52378ee8d1cSJulian Grajkowski 		device_printf(
52478ee8d1cSJulian Grajkowski 		    GET_DEV(accel_dev),
52578ee8d1cSJulian Grajkowski 		    "Waiting for device un-busy failed. Retries limit reached\n");
52678ee8d1cSJulian Grajkowski 		return EBUSY;
52778ee8d1cSJulian Grajkowski 	}
52878ee8d1cSJulian Grajkowski 
52978ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
53078ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
53178ee8d1cSJulian Grajkowski 
532*266b0663SKrzysztof Zdziarski 	if (accel_dev->hw_device->int_timer_exit)
533*266b0663SKrzysztof Zdziarski 		accel_dev->hw_device->int_timer_exit(accel_dev);
534*266b0663SKrzysztof Zdziarski 
53578ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
53678ee8d1cSJulian Grajkowski 	{
53778ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
53878ee8d1cSJulian Grajkowski 		if (!test_bit(accel_dev->accel_id, service->start_status))
53978ee8d1cSJulian Grajkowski 			continue;
54078ee8d1cSJulian Grajkowski 		clear_bit(accel_dev->accel_id, service->start_status);
54178ee8d1cSJulian Grajkowski 	}
54278ee8d1cSJulian Grajkowski 
543*266b0663SKrzysztof Zdziarski 	if (accel_dev->is_vf || !accel_dev->u1.pf.vf_info) {
544*266b0663SKrzysztof Zdziarski 		/* Remove UIO Devices */
545*266b0663SKrzysztof Zdziarski 		adf_uio_remove(accel_dev);
546*266b0663SKrzysztof Zdziarski 	}
547*266b0663SKrzysztof Zdziarski 
54878ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) {
54978ee8d1cSJulian Grajkowski 		if (adf_ae_stop(accel_dev))
55078ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
55178ee8d1cSJulian Grajkowski 				      "failed to stop AE\n");
55278ee8d1cSJulian Grajkowski 		else
55378ee8d1cSJulian Grajkowski 			clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
55478ee8d1cSJulian Grajkowski 	}
55578ee8d1cSJulian Grajkowski 
55678ee8d1cSJulian Grajkowski 	return 0;
55778ee8d1cSJulian Grajkowski }
55878ee8d1cSJulian Grajkowski 
55978ee8d1cSJulian Grajkowski /**
56078ee8d1cSJulian Grajkowski  * adf_dev_shutdown() - shutdown acceleration services and data strucutures
56178ee8d1cSJulian Grajkowski  * @accel_dev: Pointer to acceleration device
56278ee8d1cSJulian Grajkowski  *
56378ee8d1cSJulian Grajkowski  * Cleanup the ring data structures and the admin comms and arbitration
56478ee8d1cSJulian Grajkowski  * services.
56578ee8d1cSJulian Grajkowski  */
56678ee8d1cSJulian Grajkowski void
adf_dev_shutdown(struct adf_accel_dev * accel_dev)56778ee8d1cSJulian Grajkowski adf_dev_shutdown(struct adf_accel_dev *accel_dev)
56878ee8d1cSJulian Grajkowski {
56978ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
57078ee8d1cSJulian Grajkowski 	struct service_hndl *service;
57178ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
57278ee8d1cSJulian Grajkowski 
57378ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, &accel_dev->status)) {
57478ee8d1cSJulian Grajkowski 		sysctl_ctx_free(&accel_dev->sysctl_ctx);
57578ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED,
57678ee8d1cSJulian Grajkowski 			  &accel_dev->status);
57778ee8d1cSJulian Grajkowski 	}
57878ee8d1cSJulian Grajkowski 
57978ee8d1cSJulian Grajkowski 	if (!hw_data) {
58078ee8d1cSJulian Grajkowski 		device_printf(
58178ee8d1cSJulian Grajkowski 		    GET_DEV(accel_dev),
58278ee8d1cSJulian Grajkowski 		    "QAT: Failed to shutdown device - hw_data not set\n");
58378ee8d1cSJulian Grajkowski 		return;
58478ee8d1cSJulian Grajkowski 	}
58578ee8d1cSJulian Grajkowski 
58678ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
58778ee8d1cSJulian Grajkowski 		adf_ae_fw_release(accel_dev);
58878ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
58978ee8d1cSJulian Grajkowski 	}
59078ee8d1cSJulian Grajkowski 
59178ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
59278ee8d1cSJulian Grajkowski 		if (adf_ae_shutdown(accel_dev))
59378ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
59478ee8d1cSJulian Grajkowski 				      "Failed to shutdown Accel Engine\n");
59578ee8d1cSJulian Grajkowski 		else
59678ee8d1cSJulian Grajkowski 			clear_bit(ADF_STATUS_AE_INITIALISED,
59778ee8d1cSJulian Grajkowski 				  &accel_dev->status);
59878ee8d1cSJulian Grajkowski 	}
59978ee8d1cSJulian Grajkowski 
60078ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
60178ee8d1cSJulian Grajkowski 	{
60278ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
60378ee8d1cSJulian Grajkowski 		if (!test_bit(accel_dev->accel_id, service->init_status))
60478ee8d1cSJulian Grajkowski 			continue;
60578ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
60678ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
60778ee8d1cSJulian Grajkowski 				      "Failed to shutdown service %s\n",
60878ee8d1cSJulian Grajkowski 				      service->name);
60978ee8d1cSJulian Grajkowski 		else
61078ee8d1cSJulian Grajkowski 			clear_bit(accel_dev->accel_id, service->init_status);
61178ee8d1cSJulian Grajkowski 	}
61278ee8d1cSJulian Grajkowski 
61378ee8d1cSJulian Grajkowski 	hw_data->disable_iov(accel_dev);
61478ee8d1cSJulian Grajkowski 
61578ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
61678ee8d1cSJulian Grajkowski 		hw_data->free_irq(accel_dev);
61778ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
61878ee8d1cSJulian Grajkowski 	}
61978ee8d1cSJulian Grajkowski 
62078ee8d1cSJulian Grajkowski 	/* Delete configuration only if not restarting */
62178ee8d1cSJulian Grajkowski 	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
62278ee8d1cSJulian Grajkowski 		adf_cfg_del_all(accel_dev);
62378ee8d1cSJulian Grajkowski 
62478ee8d1cSJulian Grajkowski 	if (hw_data->remove_pke_stats)
62578ee8d1cSJulian Grajkowski 		hw_data->remove_pke_stats(accel_dev);
62678ee8d1cSJulian Grajkowski 
62778ee8d1cSJulian Grajkowski 	if (hw_data->remove_misc_error)
62878ee8d1cSJulian Grajkowski 		hw_data->remove_misc_error(accel_dev);
62978ee8d1cSJulian Grajkowski 
63078ee8d1cSJulian Grajkowski 	if (hw_data->exit_ras)
63178ee8d1cSJulian Grajkowski 		hw_data->exit_ras(accel_dev);
63278ee8d1cSJulian Grajkowski 
63378ee8d1cSJulian Grajkowski 	if (hw_data->exit_arb)
63478ee8d1cSJulian Grajkowski 		hw_data->exit_arb(accel_dev);
63578ee8d1cSJulian Grajkowski 
63678ee8d1cSJulian Grajkowski 	if (hw_data->exit_admin_comms)
63778ee8d1cSJulian Grajkowski 		hw_data->exit_admin_comms(accel_dev);
63878ee8d1cSJulian Grajkowski 
63978ee8d1cSJulian Grajkowski 	if (hw_data->exit_accel_units)
64078ee8d1cSJulian Grajkowski 		hw_data->exit_accel_units(accel_dev);
64178ee8d1cSJulian Grajkowski 
64278ee8d1cSJulian Grajkowski 	adf_cleanup_etr_data(accel_dev);
64378ee8d1cSJulian Grajkowski 	if (hw_data->restore_device)
64478ee8d1cSJulian Grajkowski 		hw_data->restore_device(accel_dev);
64578ee8d1cSJulian Grajkowski }
64678ee8d1cSJulian Grajkowski 
64778ee8d1cSJulian Grajkowski /**
64878ee8d1cSJulian Grajkowski  * adf_dev_reset() - Reset acceleration service for the given accel device
64978ee8d1cSJulian Grajkowski  * @accel_dev:    Pointer to acceleration device.
65078ee8d1cSJulian Grajkowski  * @mode: Specifies reset mode - synchronous or asynchronous.
65178ee8d1cSJulian Grajkowski  * Function notifies all the registered services that the acceleration device
65278ee8d1cSJulian Grajkowski  * is resetting.
65378ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
65478ee8d1cSJulian Grajkowski  *
65578ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
65678ee8d1cSJulian Grajkowski  */
65778ee8d1cSJulian Grajkowski int
adf_dev_reset(struct adf_accel_dev * accel_dev,enum adf_dev_reset_mode mode)65878ee8d1cSJulian Grajkowski adf_dev_reset(struct adf_accel_dev *accel_dev, enum adf_dev_reset_mode mode)
65978ee8d1cSJulian Grajkowski {
66078ee8d1cSJulian Grajkowski 	return adf_dev_aer_schedule_reset(accel_dev, mode);
66178ee8d1cSJulian Grajkowski }
66278ee8d1cSJulian Grajkowski 
66378ee8d1cSJulian Grajkowski int
adf_dev_restarting_notify(struct adf_accel_dev * accel_dev)66478ee8d1cSJulian Grajkowski adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
66578ee8d1cSJulian Grajkowski {
66678ee8d1cSJulian Grajkowski 	struct service_hndl *service;
66778ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
66878ee8d1cSJulian Grajkowski 
66978ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
67078ee8d1cSJulian Grajkowski 	{
67178ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
67278ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
67378ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
67478ee8d1cSJulian Grajkowski 				      "Failed to restart service %s.\n",
67578ee8d1cSJulian Grajkowski 				      service->name);
67678ee8d1cSJulian Grajkowski 	}
67778ee8d1cSJulian Grajkowski 	return 0;
67878ee8d1cSJulian Grajkowski }
67978ee8d1cSJulian Grajkowski 
68078ee8d1cSJulian Grajkowski int
adf_dev_restarting_notify_sync(struct adf_accel_dev * accel_dev)68178ee8d1cSJulian Grajkowski adf_dev_restarting_notify_sync(struct adf_accel_dev *accel_dev)
68278ee8d1cSJulian Grajkowski {
68378ee8d1cSJulian Grajkowski 	int times;
68478ee8d1cSJulian Grajkowski 
68578ee8d1cSJulian Grajkowski 	adf_dev_restarting_notify(accel_dev);
68678ee8d1cSJulian Grajkowski 	for (times = 0; times < ADF_STOP_RETRY; times++) {
68778ee8d1cSJulian Grajkowski 		if (!adf_dev_in_use(accel_dev))
68878ee8d1cSJulian Grajkowski 			break;
68978ee8d1cSJulian Grajkowski 		dev_dbg(GET_DEV(accel_dev), "retry times=%d\n", times);
69078ee8d1cSJulian Grajkowski 		pause_ms("adfstop", 100);
69178ee8d1cSJulian Grajkowski 	}
69278ee8d1cSJulian Grajkowski 	if (adf_dev_in_use(accel_dev)) {
69378ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
69478ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
69578ee8d1cSJulian Grajkowski 			      "Device still in use during reset sequence.\n");
69678ee8d1cSJulian Grajkowski 		return EBUSY;
69778ee8d1cSJulian Grajkowski 	}
69878ee8d1cSJulian Grajkowski 
69978ee8d1cSJulian Grajkowski 	return 0;
70078ee8d1cSJulian Grajkowski }
70178ee8d1cSJulian Grajkowski 
70278ee8d1cSJulian Grajkowski int
adf_dev_stop_notify_sync(struct adf_accel_dev * accel_dev)70378ee8d1cSJulian Grajkowski adf_dev_stop_notify_sync(struct adf_accel_dev *accel_dev)
70478ee8d1cSJulian Grajkowski {
70578ee8d1cSJulian Grajkowski 	int times;
70678ee8d1cSJulian Grajkowski 
70778ee8d1cSJulian Grajkowski 	struct service_hndl *service;
70878ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
70978ee8d1cSJulian Grajkowski 
71078ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
71178ee8d1cSJulian Grajkowski 	{
71278ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
71378ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_STOP))
71478ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
71578ee8d1cSJulian Grajkowski 				      "Failed to restart service %s.\n",
71678ee8d1cSJulian Grajkowski 				      service->name);
71778ee8d1cSJulian Grajkowski 	}
71878ee8d1cSJulian Grajkowski 
71978ee8d1cSJulian Grajkowski 	for (times = 0; times < ADF_STOP_RETRY; times++) {
72078ee8d1cSJulian Grajkowski 		if (!adf_dev_in_use(accel_dev))
72178ee8d1cSJulian Grajkowski 			break;
72278ee8d1cSJulian Grajkowski 		dev_dbg(GET_DEV(accel_dev), "retry times=%d\n", times);
72378ee8d1cSJulian Grajkowski 		pause_ms("adfstop", 100);
72478ee8d1cSJulian Grajkowski 	}
72578ee8d1cSJulian Grajkowski 	if (adf_dev_in_use(accel_dev)) {
72678ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
72778ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
72878ee8d1cSJulian Grajkowski 			      "Device still in use during stop sequence.\n");
72978ee8d1cSJulian Grajkowski 		return EBUSY;
73078ee8d1cSJulian Grajkowski 	}
73178ee8d1cSJulian Grajkowski 
73278ee8d1cSJulian Grajkowski 	return 0;
73378ee8d1cSJulian Grajkowski }
73478ee8d1cSJulian Grajkowski 
73578ee8d1cSJulian Grajkowski int
adf_dev_restarted_notify(struct adf_accel_dev * accel_dev)73678ee8d1cSJulian Grajkowski adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
73778ee8d1cSJulian Grajkowski {
73878ee8d1cSJulian Grajkowski 	struct service_hndl *service;
73978ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
74078ee8d1cSJulian Grajkowski 
74178ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
74278ee8d1cSJulian Grajkowski 	{
74378ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
74478ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
74578ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
74678ee8d1cSJulian Grajkowski 				      "Failed to restart service %s.\n",
74778ee8d1cSJulian Grajkowski 				      service->name);
74878ee8d1cSJulian Grajkowski 	}
74978ee8d1cSJulian Grajkowski 	return 0;
75078ee8d1cSJulian Grajkowski }
751