xref: /freebsd/sys/dev/qat/qat_common/adf_init.c (revision ae1dc27639c88038d150660c4096753e210aec42)
178ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
2c38bafeeSHareshx Sankar Raj /* Copyright(c) 2007-2025 Intel Corporation */
378ee8d1cSJulian Grajkowski #include "qat_freebsd.h"
478ee8d1cSJulian Grajkowski #include "adf_cfg.h"
578ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
6c38bafeeSHareshx Sankar Raj #include "adf_dbgfs.h"
778ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
878ee8d1cSJulian Grajkowski #include "icp_qat_uclo.h"
978ee8d1cSJulian Grajkowski #include "icp_qat_fw.h"
1078ee8d1cSJulian Grajkowski #include "icp_qat_fw_init_admin.h"
1178ee8d1cSJulian Grajkowski #include "adf_cfg_strings.h"
1278ee8d1cSJulian Grajkowski #include "adf_dev_err.h"
13266b0663SKrzysztof Zdziarski #include "adf_uio.h"
1478ee8d1cSJulian Grajkowski #include "adf_transport_access_macros.h"
1578ee8d1cSJulian Grajkowski #include "adf_transport_internal.h"
1678ee8d1cSJulian Grajkowski #include <sys/mutex.h>
1778ee8d1cSJulian Grajkowski #include <linux/delay.h>
1878ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
1978ee8d1cSJulian Grajkowski #include "adf_cfg.h"
2078ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
2178ee8d1cSJulian Grajkowski #include "icp_qat_fw.h"
2278ee8d1cSJulian Grajkowski 
23*ded037e6SHareshx Sankar Raj #if defined(QAT_UIO)
24*ded037e6SHareshx Sankar Raj #include "adf_cfg_device.h"
25*ded037e6SHareshx Sankar Raj #endif /* QAT_UIO*/
26*ded037e6SHareshx Sankar Raj 
2778ee8d1cSJulian Grajkowski /* Mask used to check the CompressAndVerify capability bit */
2878ee8d1cSJulian Grajkowski #define DC_CNV_EXTENDED_CAPABILITY (0x01)
2978ee8d1cSJulian Grajkowski 
3078ee8d1cSJulian Grajkowski /* Mask used to check the CompressAndVerifyAndRecover capability bit */
3178ee8d1cSJulian Grajkowski #define DC_CNVNR_EXTENDED_CAPABILITY (0x100)
3278ee8d1cSJulian Grajkowski 
3378ee8d1cSJulian Grajkowski static LIST_HEAD(service_table);
3478ee8d1cSJulian Grajkowski static DEFINE_MUTEX(service_lock);
3578ee8d1cSJulian Grajkowski 
36*ded037e6SHareshx Sankar Raj static int adf_dev_init_locked(struct adf_accel_dev *accel_dev);
37*ded037e6SHareshx Sankar Raj static int adf_dev_start_locked(struct adf_accel_dev *accel_dev);
38*ded037e6SHareshx Sankar Raj static int adf_dev_stop_locked(struct adf_accel_dev *accel_dev);
39*ded037e6SHareshx Sankar Raj static void adf_dev_shutdown_locked(struct adf_accel_dev *accel_dev);
40*ded037e6SHareshx Sankar Raj 
4178ee8d1cSJulian Grajkowski static void
adf_service_add(struct service_hndl * service)4278ee8d1cSJulian Grajkowski adf_service_add(struct service_hndl *service)
4378ee8d1cSJulian Grajkowski {
4478ee8d1cSJulian Grajkowski 	mutex_lock(&service_lock);
4578ee8d1cSJulian Grajkowski 	list_add(&service->list, &service_table);
4678ee8d1cSJulian Grajkowski 	mutex_unlock(&service_lock);
4778ee8d1cSJulian Grajkowski }
4878ee8d1cSJulian Grajkowski 
4978ee8d1cSJulian Grajkowski int
adf_service_register(struct service_hndl * service)5078ee8d1cSJulian Grajkowski adf_service_register(struct service_hndl *service)
5178ee8d1cSJulian Grajkowski {
5278ee8d1cSJulian Grajkowski 	memset(service->init_status, 0, sizeof(service->init_status));
5378ee8d1cSJulian Grajkowski 	memset(service->start_status, 0, sizeof(service->start_status));
5478ee8d1cSJulian Grajkowski 	adf_service_add(service);
5578ee8d1cSJulian Grajkowski 	return 0;
5678ee8d1cSJulian Grajkowski }
5778ee8d1cSJulian Grajkowski 
5878ee8d1cSJulian Grajkowski static void
adf_service_remove(struct service_hndl * service)5978ee8d1cSJulian Grajkowski adf_service_remove(struct service_hndl *service)
6078ee8d1cSJulian Grajkowski {
6178ee8d1cSJulian Grajkowski 	mutex_lock(&service_lock);
6278ee8d1cSJulian Grajkowski 	list_del(&service->list);
6378ee8d1cSJulian Grajkowski 	mutex_unlock(&service_lock);
6478ee8d1cSJulian Grajkowski }
6578ee8d1cSJulian Grajkowski 
6678ee8d1cSJulian Grajkowski int
adf_service_unregister(struct service_hndl * service)6778ee8d1cSJulian Grajkowski adf_service_unregister(struct service_hndl *service)
6878ee8d1cSJulian Grajkowski {
6978ee8d1cSJulian Grajkowski 	int i;
7078ee8d1cSJulian Grajkowski 
7178ee8d1cSJulian Grajkowski 	for (i = 0; i < ARRAY_SIZE(service->init_status); i++) {
7278ee8d1cSJulian Grajkowski 		if (service->init_status[i] || service->start_status[i]) {
7378ee8d1cSJulian Grajkowski 			pr_err("QAT: Could not remove active service [%d]\n",
7478ee8d1cSJulian Grajkowski 			       i);
7578ee8d1cSJulian Grajkowski 			return EFAULT;
7678ee8d1cSJulian Grajkowski 		}
7778ee8d1cSJulian Grajkowski 	}
7878ee8d1cSJulian Grajkowski 	adf_service_remove(service);
7978ee8d1cSJulian Grajkowski 	return 0;
8078ee8d1cSJulian Grajkowski }
8178ee8d1cSJulian Grajkowski 
8278ee8d1cSJulian Grajkowski static int
adf_cfg_add_device_params(struct adf_accel_dev * accel_dev)8378ee8d1cSJulian Grajkowski adf_cfg_add_device_params(struct adf_accel_dev *accel_dev)
8478ee8d1cSJulian Grajkowski {
8578ee8d1cSJulian Grajkowski 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
8678ee8d1cSJulian Grajkowski 	char hw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
8778ee8d1cSJulian Grajkowski 	char mmp_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
8878ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = NULL;
8978ee8d1cSJulian Grajkowski 	unsigned long val;
9078ee8d1cSJulian Grajkowski 	if (!accel_dev)
9178ee8d1cSJulian Grajkowski 		return -EINVAL;
9278ee8d1cSJulian Grajkowski 
9378ee8d1cSJulian Grajkowski 	hw_data = accel_dev->hw_device;
9478ee8d1cSJulian Grajkowski 
9578ee8d1cSJulian Grajkowski 	if (adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC))
9678ee8d1cSJulian Grajkowski 		goto err;
9778ee8d1cSJulian Grajkowski 
9878ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_MAX_BANKS);
9978ee8d1cSJulian Grajkowski 	val = GET_MAX_BANKS(accel_dev);
10078ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
10178ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
10278ee8d1cSJulian Grajkowski 		goto err;
10378ee8d1cSJulian Grajkowski 
10478ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_CAPABILITIES_MASK);
10578ee8d1cSJulian Grajkowski 	val = hw_data->accel_capabilities_mask;
10678ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
10778ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)val, ADF_HEX))
10878ee8d1cSJulian Grajkowski 		goto err;
10978ee8d1cSJulian Grajkowski 
11078ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_PKG_ID);
11178ee8d1cSJulian Grajkowski 	val = accel_dev->accel_id;
11278ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
11378ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
11478ee8d1cSJulian Grajkowski 		goto err;
11578ee8d1cSJulian Grajkowski 
11678ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_NODE_ID);
11778ee8d1cSJulian Grajkowski 	val = dev_to_node(GET_DEV(accel_dev));
11878ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
11978ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
12078ee8d1cSJulian Grajkowski 		goto err;
12178ee8d1cSJulian Grajkowski 
12278ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DEV_MAX_RINGS_PER_BANK);
12378ee8d1cSJulian Grajkowski 	val = hw_data->num_rings_per_bank;
12478ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
12578ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC))
12678ee8d1cSJulian Grajkowski 		goto err;
12778ee8d1cSJulian Grajkowski 
12878ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_HW_REV_ID_KEY);
12978ee8d1cSJulian Grajkowski 	snprintf(hw_version,
13078ee8d1cSJulian Grajkowski 		 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
13178ee8d1cSJulian Grajkowski 		 "%d",
13278ee8d1cSJulian Grajkowski 		 accel_dev->accel_pci_dev.revid);
13378ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
13478ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)hw_version, ADF_STR))
13578ee8d1cSJulian Grajkowski 		goto err;
13678ee8d1cSJulian Grajkowski 
13778ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_MMP_VER_KEY);
13878ee8d1cSJulian Grajkowski 	snprintf(mmp_version,
13978ee8d1cSJulian Grajkowski 		 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
14078ee8d1cSJulian Grajkowski 		 "%d.%d.%d",
14178ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.mmp_version_major,
14278ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.mmp_version_minor,
14378ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.mmp_version_patch);
14478ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
14578ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)mmp_version, ADF_STR))
14678ee8d1cSJulian Grajkowski 		goto err;
14778ee8d1cSJulian Grajkowski 
14878ee8d1cSJulian Grajkowski 	return 0;
14978ee8d1cSJulian Grajkowski err:
15078ee8d1cSJulian Grajkowski 	device_printf(GET_DEV(accel_dev),
15178ee8d1cSJulian Grajkowski 		      "Failed to add internal values to accel_dev cfg\n");
15278ee8d1cSJulian Grajkowski 	return -EINVAL;
15378ee8d1cSJulian Grajkowski }
15478ee8d1cSJulian Grajkowski 
15578ee8d1cSJulian Grajkowski static int
adf_cfg_add_fw_version(struct adf_accel_dev * accel_dev)15678ee8d1cSJulian Grajkowski adf_cfg_add_fw_version(struct adf_accel_dev *accel_dev)
15778ee8d1cSJulian Grajkowski {
15878ee8d1cSJulian Grajkowski 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
15978ee8d1cSJulian Grajkowski 	char fw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
16078ee8d1cSJulian Grajkowski 
16178ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_UOF_VER_KEY);
16278ee8d1cSJulian Grajkowski 	snprintf(fw_version,
16378ee8d1cSJulian Grajkowski 		 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
16478ee8d1cSJulian Grajkowski 		 "%d.%d.%d",
16578ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.fw_version_major,
16678ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.fw_version_minor,
16778ee8d1cSJulian Grajkowski 		 accel_dev->fw_versions.fw_version_patch);
16878ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
16978ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)fw_version, ADF_STR))
17078ee8d1cSJulian Grajkowski 		return EFAULT;
17178ee8d1cSJulian Grajkowski 
17278ee8d1cSJulian Grajkowski 	return 0;
17378ee8d1cSJulian Grajkowski }
17478ee8d1cSJulian Grajkowski 
17578ee8d1cSJulian Grajkowski static int
adf_cfg_add_ext_params(struct adf_accel_dev * accel_dev)17678ee8d1cSJulian Grajkowski adf_cfg_add_ext_params(struct adf_accel_dev *accel_dev)
17778ee8d1cSJulian Grajkowski {
17878ee8d1cSJulian Grajkowski 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
17978ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
18078ee8d1cSJulian Grajkowski 	unsigned long val;
18178ee8d1cSJulian Grajkowski 
18278ee8d1cSJulian Grajkowski 	snprintf(key, sizeof(key), ADF_DC_EXTENDED_FEATURES);
18378ee8d1cSJulian Grajkowski 
18478ee8d1cSJulian Grajkowski 	val = hw_data->extended_dc_capabilities;
18578ee8d1cSJulian Grajkowski 	if (adf_cfg_add_key_value_param(
18678ee8d1cSJulian Grajkowski 		accel_dev, ADF_GENERAL_SEC, key, (void *)val, ADF_HEX))
18778ee8d1cSJulian Grajkowski 		return -EINVAL;
18878ee8d1cSJulian Grajkowski 
18978ee8d1cSJulian Grajkowski 	return 0;
19078ee8d1cSJulian Grajkowski }
19178ee8d1cSJulian Grajkowski 
19278ee8d1cSJulian Grajkowski void
adf_error_notifier(uintptr_t arg)19378ee8d1cSJulian Grajkowski adf_error_notifier(uintptr_t arg)
19478ee8d1cSJulian Grajkowski {
19578ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = (struct adf_accel_dev *)arg;
19678ee8d1cSJulian Grajkowski 	struct service_hndl *service;
19778ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
19878ee8d1cSJulian Grajkowski 
19978ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
20078ee8d1cSJulian Grajkowski 	{
20178ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
20278ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_ERROR))
20378ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
20478ee8d1cSJulian Grajkowski 				      "Failed to send error event to %s.\n",
20578ee8d1cSJulian Grajkowski 				      service->name);
20678ee8d1cSJulian Grajkowski 	}
20778ee8d1cSJulian Grajkowski }
20878ee8d1cSJulian Grajkowski 
20978ee8d1cSJulian Grajkowski /**
21078ee8d1cSJulian Grajkowski  * adf_set_ssm_wdtimer() - Initialize the slice hang watchdog timer.
21178ee8d1cSJulian Grajkowski  *
21278ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
21378ee8d1cSJulian Grajkowski  */
21478ee8d1cSJulian Grajkowski int
adf_set_ssm_wdtimer(struct adf_accel_dev * accel_dev)21578ee8d1cSJulian Grajkowski adf_set_ssm_wdtimer(struct adf_accel_dev *accel_dev)
21678ee8d1cSJulian Grajkowski {
21778ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
21878ee8d1cSJulian Grajkowski 	struct adf_bar *misc_bar =
21978ee8d1cSJulian Grajkowski 	    &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
22078ee8d1cSJulian Grajkowski 	struct resource *csr = misc_bar->virt_addr;
22178ee8d1cSJulian Grajkowski 	u32 i;
22278ee8d1cSJulian Grajkowski 	unsigned int mask;
22378ee8d1cSJulian Grajkowski 	u32 clk_per_sec = hw_data->get_clock_speed(hw_data);
22478ee8d1cSJulian Grajkowski 	u32 timer_val = ADF_WDT_TIMER_SYM_COMP_MS * (clk_per_sec / 1000);
225a977168cSMichal Gulbicki 	u32 timer_val_pke = ADF_GEN2_SSM_WDT_PKE_DEFAULT_VALUE;
22678ee8d1cSJulian Grajkowski 	char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
22778ee8d1cSJulian Grajkowski 
22878ee8d1cSJulian Grajkowski 	/* Get Watch Dog Timer for CySym+Comp from the configuration */
22978ee8d1cSJulian Grajkowski 	if (!adf_cfg_get_param_value(accel_dev,
23078ee8d1cSJulian Grajkowski 				     ADF_GENERAL_SEC,
23178ee8d1cSJulian Grajkowski 				     ADF_DEV_SSM_WDT_BULK,
23278ee8d1cSJulian Grajkowski 				     (char *)timer_str)) {
23378ee8d1cSJulian Grajkowski 		if (!compat_strtouint((char *)timer_str,
23478ee8d1cSJulian Grajkowski 				      ADF_CFG_BASE_DEC,
23578ee8d1cSJulian Grajkowski 				      &timer_val))
23678ee8d1cSJulian Grajkowski 			/* Convert msec to CPP clocks */
23778ee8d1cSJulian Grajkowski 			timer_val = timer_val * (clk_per_sec / 1000);
23878ee8d1cSJulian Grajkowski 	}
23978ee8d1cSJulian Grajkowski 	/* Get Watch Dog Timer for CyAsym from the configuration */
24078ee8d1cSJulian Grajkowski 	if (!adf_cfg_get_param_value(accel_dev,
24178ee8d1cSJulian Grajkowski 				     ADF_GENERAL_SEC,
24278ee8d1cSJulian Grajkowski 				     ADF_DEV_SSM_WDT_PKE,
24378ee8d1cSJulian Grajkowski 				     (char *)timer_str)) {
24478ee8d1cSJulian Grajkowski 		if (!compat_strtouint((char *)timer_str,
24578ee8d1cSJulian Grajkowski 				      ADF_CFG_BASE_DEC,
24678ee8d1cSJulian Grajkowski 				      &timer_val_pke))
24778ee8d1cSJulian Grajkowski 			/* Convert msec to CPP clocks */
24878ee8d1cSJulian Grajkowski 			timer_val_pke = timer_val_pke * (clk_per_sec / 1000);
24978ee8d1cSJulian Grajkowski 	}
25078ee8d1cSJulian Grajkowski 
25178ee8d1cSJulian Grajkowski 	for (i = 0, mask = hw_data->accel_mask; mask; i++, mask >>= 1) {
25278ee8d1cSJulian Grajkowski 		if (!(mask & 1))
25378ee8d1cSJulian Grajkowski 			continue;
25478ee8d1cSJulian Grajkowski 		/* Enable Watch Dog Timer for CySym + Comp */
25578ee8d1cSJulian Grajkowski 		ADF_CSR_WR(csr, ADF_SSMWDT(i), timer_val);
25678ee8d1cSJulian Grajkowski 		/* Enable Watch Dog Timer for CyAsym */
25778ee8d1cSJulian Grajkowski 		ADF_CSR_WR(csr, ADF_SSMWDTPKE(i), timer_val_pke);
25878ee8d1cSJulian Grajkowski 	}
25978ee8d1cSJulian Grajkowski 	return 0;
26078ee8d1cSJulian Grajkowski }
26178ee8d1cSJulian Grajkowski 
26278ee8d1cSJulian Grajkowski /**
26378ee8d1cSJulian Grajkowski  * adf_dev_init() - Init data structures and services for the given accel device
26478ee8d1cSJulian Grajkowski  * @accel_dev: Pointer to acceleration device.
26578ee8d1cSJulian Grajkowski  *
26678ee8d1cSJulian Grajkowski  * Initialize the ring data structures and the admin comms and arbitration
26778ee8d1cSJulian Grajkowski  * services.
26878ee8d1cSJulian Grajkowski  *
26978ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
27078ee8d1cSJulian Grajkowski  */
27178ee8d1cSJulian Grajkowski int
adf_dev_init(struct adf_accel_dev * accel_dev)27278ee8d1cSJulian Grajkowski adf_dev_init(struct adf_accel_dev *accel_dev)
27378ee8d1cSJulian Grajkowski {
274*ded037e6SHareshx Sankar Raj 	int ret = 0;
275*ded037e6SHareshx Sankar Raj 
276*ded037e6SHareshx Sankar Raj 	mutex_lock(&accel_dev->lock);
277*ded037e6SHareshx Sankar Raj 	ret = adf_dev_init_locked(accel_dev);
278*ded037e6SHareshx Sankar Raj 	mutex_unlock(&accel_dev->lock);
279*ded037e6SHareshx Sankar Raj 
280*ded037e6SHareshx Sankar Raj 	return ret;
281*ded037e6SHareshx Sankar Raj }
282*ded037e6SHareshx Sankar Raj 
283*ded037e6SHareshx Sankar Raj static int
adf_dev_init_locked(struct adf_accel_dev * accel_dev)284*ded037e6SHareshx Sankar Raj adf_dev_init_locked(struct adf_accel_dev *accel_dev)
285*ded037e6SHareshx Sankar Raj {
28678ee8d1cSJulian Grajkowski 	struct service_hndl *service;
28778ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
28878ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
28978ee8d1cSJulian Grajkowski 	char value[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
29078ee8d1cSJulian Grajkowski 	int ret = 0;
29178ee8d1cSJulian Grajkowski 	sysctl_ctx_init(&accel_dev->sysctl_ctx);
29278ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, &accel_dev->status);
29378ee8d1cSJulian Grajkowski 
29478ee8d1cSJulian Grajkowski 	if (!hw_data) {
29578ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
29678ee8d1cSJulian Grajkowski 			      "Failed to init device - hw_data not set\n");
29778ee8d1cSJulian Grajkowski 		return EFAULT;
29878ee8d1cSJulian Grajkowski 	}
29978ee8d1cSJulian Grajkowski 	if (hw_data->reset_hw_units)
30078ee8d1cSJulian Grajkowski 		hw_data->reset_hw_units(accel_dev);
30178ee8d1cSJulian Grajkowski 
30278ee8d1cSJulian Grajkowski 	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status) &&
30378ee8d1cSJulian Grajkowski 	    !accel_dev->is_vf) {
30478ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Device not configured\n");
30578ee8d1cSJulian Grajkowski 		return EFAULT;
30678ee8d1cSJulian Grajkowski 	}
30778ee8d1cSJulian Grajkowski 
30878ee8d1cSJulian Grajkowski 	if (adf_init_etr_data(accel_dev)) {
30978ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Failed initialize etr\n");
31078ee8d1cSJulian Grajkowski 		return EFAULT;
31178ee8d1cSJulian Grajkowski 	}
31278ee8d1cSJulian Grajkowski 
313a977168cSMichal Gulbicki 	if (hw_data->init_device && hw_data->init_device(accel_dev)) {
314a977168cSMichal Gulbicki 		device_printf(GET_DEV(accel_dev),
315a977168cSMichal Gulbicki 			      "Failed to initialize device\n");
316a977168cSMichal Gulbicki 		return EFAULT;
317a977168cSMichal Gulbicki 	}
318a977168cSMichal Gulbicki 
31978ee8d1cSJulian Grajkowski 	if (hw_data->init_accel_units && hw_data->init_accel_units(accel_dev)) {
32078ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
32178ee8d1cSJulian Grajkowski 			      "Failed initialize accel_units\n");
32278ee8d1cSJulian Grajkowski 		return EFAULT;
32378ee8d1cSJulian Grajkowski 	}
32478ee8d1cSJulian Grajkowski 
32578ee8d1cSJulian Grajkowski 	if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) {
32678ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
32778ee8d1cSJulian Grajkowski 			      "Failed initialize admin comms\n");
32878ee8d1cSJulian Grajkowski 		return EFAULT;
32978ee8d1cSJulian Grajkowski 	}
33078ee8d1cSJulian Grajkowski 
33178ee8d1cSJulian Grajkowski 	if (hw_data->init_arb && hw_data->init_arb(accel_dev)) {
33278ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
33378ee8d1cSJulian Grajkowski 			      "Failed initialize hw arbiter\n");
33478ee8d1cSJulian Grajkowski 		return EFAULT;
33578ee8d1cSJulian Grajkowski 	}
33678ee8d1cSJulian Grajkowski 
33778ee8d1cSJulian Grajkowski 	if (hw_data->set_asym_rings_mask)
33878ee8d1cSJulian Grajkowski 		hw_data->set_asym_rings_mask(accel_dev);
33978ee8d1cSJulian Grajkowski 
34078ee8d1cSJulian Grajkowski 	hw_data->enable_ints(accel_dev);
34178ee8d1cSJulian Grajkowski 
34278ee8d1cSJulian Grajkowski 	if (adf_ae_init(accel_dev)) {
34378ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
34478ee8d1cSJulian Grajkowski 			      "Failed to initialise Acceleration Engine\n");
34578ee8d1cSJulian Grajkowski 		return EFAULT;
34678ee8d1cSJulian Grajkowski 	}
34778ee8d1cSJulian Grajkowski 
34878ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
34978ee8d1cSJulian Grajkowski 
35078ee8d1cSJulian Grajkowski 	if (adf_ae_fw_load(accel_dev)) {
35178ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
35278ee8d1cSJulian Grajkowski 			      "Failed to load acceleration FW\n");
35378ee8d1cSJulian Grajkowski 		return EFAULT;
35478ee8d1cSJulian Grajkowski 	}
35578ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
35678ee8d1cSJulian Grajkowski 
35778ee8d1cSJulian Grajkowski 	if (hw_data->alloc_irq(accel_dev)) {
35878ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
35978ee8d1cSJulian Grajkowski 			      "Failed to allocate interrupts\n");
36078ee8d1cSJulian Grajkowski 		return EFAULT;
36178ee8d1cSJulian Grajkowski 	}
36278ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
36378ee8d1cSJulian Grajkowski 
36478ee8d1cSJulian Grajkowski 	if (hw_data->init_ras && hw_data->init_ras(accel_dev)) {
36578ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Failed to init RAS\n");
36678ee8d1cSJulian Grajkowski 		return EFAULT;
36778ee8d1cSJulian Grajkowski 	}
36878ee8d1cSJulian Grajkowski 
36978ee8d1cSJulian Grajkowski 	hw_data->enable_ints(accel_dev);
37078ee8d1cSJulian Grajkowski 
37178ee8d1cSJulian Grajkowski 	hw_data->enable_error_correction(accel_dev);
37278ee8d1cSJulian Grajkowski 
373266b0663SKrzysztof Zdziarski 	ret = hw_data->csr_info.pfvf_ops.enable_comms(accel_dev);
374266b0663SKrzysztof Zdziarski 	if (ret)
375266b0663SKrzysztof Zdziarski 		return ret;
37678ee8d1cSJulian Grajkowski 
37778ee8d1cSJulian Grajkowski 	if (adf_cfg_add_device_params(accel_dev))
37878ee8d1cSJulian Grajkowski 		return EFAULT;
37978ee8d1cSJulian Grajkowski 
38078ee8d1cSJulian Grajkowski 	if (hw_data->add_pke_stats && hw_data->add_pke_stats(accel_dev))
38178ee8d1cSJulian Grajkowski 		return EFAULT;
38278ee8d1cSJulian Grajkowski 
38378ee8d1cSJulian Grajkowski 	if (hw_data->add_misc_error && hw_data->add_misc_error(accel_dev))
38478ee8d1cSJulian Grajkowski 		return EFAULT;
38578ee8d1cSJulian Grajkowski 	/*
38678ee8d1cSJulian Grajkowski 	 * Subservice initialisation is divided into two stages: init and start.
38778ee8d1cSJulian Grajkowski 	 * This is to facilitate any ordering dependencies between services
38878ee8d1cSJulian Grajkowski 	 * prior to starting any of the accelerators.
38978ee8d1cSJulian Grajkowski 	 */
39078ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
39178ee8d1cSJulian Grajkowski 	{
39278ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
39378ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
39478ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
39578ee8d1cSJulian Grajkowski 				      "Failed to initialise service %s\n",
39678ee8d1cSJulian Grajkowski 				      service->name);
39778ee8d1cSJulian Grajkowski 			return EFAULT;
39878ee8d1cSJulian Grajkowski 		}
39978ee8d1cSJulian Grajkowski 		set_bit(accel_dev->accel_id, service->init_status);
40078ee8d1cSJulian Grajkowski 	}
40178ee8d1cSJulian Grajkowski 
40278ee8d1cSJulian Grajkowski 	/* Read autoreset on error parameter */
40378ee8d1cSJulian Grajkowski 	ret = adf_cfg_get_param_value(accel_dev,
40478ee8d1cSJulian Grajkowski 				      ADF_GENERAL_SEC,
40578ee8d1cSJulian Grajkowski 				      ADF_AUTO_RESET_ON_ERROR,
40678ee8d1cSJulian Grajkowski 				      value);
40778ee8d1cSJulian Grajkowski 	if (!ret) {
40878ee8d1cSJulian Grajkowski 		if (compat_strtouint(value,
40978ee8d1cSJulian Grajkowski 				     10,
41078ee8d1cSJulian Grajkowski 				     &accel_dev->autoreset_on_error)) {
41178ee8d1cSJulian Grajkowski 			device_printf(
41278ee8d1cSJulian Grajkowski 			    GET_DEV(accel_dev),
41378ee8d1cSJulian Grajkowski 			    "Failed converting %s to a decimal value\n",
41478ee8d1cSJulian Grajkowski 			    ADF_AUTO_RESET_ON_ERROR);
41578ee8d1cSJulian Grajkowski 			return EFAULT;
41678ee8d1cSJulian Grajkowski 		}
41778ee8d1cSJulian Grajkowski 	}
41878ee8d1cSJulian Grajkowski 
41978ee8d1cSJulian Grajkowski 	return 0;
42078ee8d1cSJulian Grajkowski }
42178ee8d1cSJulian Grajkowski 
42278ee8d1cSJulian Grajkowski /**
42378ee8d1cSJulian Grajkowski  * adf_dev_start() - Start acceleration service for the given accel device
42478ee8d1cSJulian Grajkowski  * @accel_dev:    Pointer to acceleration device.
42578ee8d1cSJulian Grajkowski  *
42678ee8d1cSJulian Grajkowski  * Function notifies all the registered services that the acceleration device
42778ee8d1cSJulian Grajkowski  * is ready to be used.
42878ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
42978ee8d1cSJulian Grajkowski  *
43078ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
43178ee8d1cSJulian Grajkowski  */
43278ee8d1cSJulian Grajkowski int
adf_dev_start(struct adf_accel_dev * accel_dev)43378ee8d1cSJulian Grajkowski adf_dev_start(struct adf_accel_dev *accel_dev)
43478ee8d1cSJulian Grajkowski {
435*ded037e6SHareshx Sankar Raj 	int ret = 0;
436*ded037e6SHareshx Sankar Raj 
437*ded037e6SHareshx Sankar Raj 	mutex_lock(&accel_dev->lock);
438*ded037e6SHareshx Sankar Raj 	ret = adf_dev_start_locked(accel_dev);
439*ded037e6SHareshx Sankar Raj 	mutex_unlock(&accel_dev->lock);
440*ded037e6SHareshx Sankar Raj 
441*ded037e6SHareshx Sankar Raj 	return ret;
442*ded037e6SHareshx Sankar Raj }
443*ded037e6SHareshx Sankar Raj 
444*ded037e6SHareshx Sankar Raj static int
adf_dev_start_locked(struct adf_accel_dev * accel_dev)445*ded037e6SHareshx Sankar Raj adf_dev_start_locked(struct adf_accel_dev *accel_dev)
446*ded037e6SHareshx Sankar Raj {
44778ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
44878ee8d1cSJulian Grajkowski 	struct service_hndl *service;
44978ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
45078ee8d1cSJulian Grajkowski 
45178ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_STARTING, &accel_dev->status);
45278ee8d1cSJulian Grajkowski 	if (adf_ae_start(accel_dev)) {
45378ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "AE Start Failed\n");
45478ee8d1cSJulian Grajkowski 		return EFAULT;
45578ee8d1cSJulian Grajkowski 	}
45678ee8d1cSJulian Grajkowski 
45778ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
45878ee8d1cSJulian Grajkowski 	if (hw_data->send_admin_init(accel_dev)) {
45978ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
46078ee8d1cSJulian Grajkowski 			      "Failed to send init message\n");
46178ee8d1cSJulian Grajkowski 		return EFAULT;
46278ee8d1cSJulian Grajkowski 	}
46378ee8d1cSJulian Grajkowski 
46478ee8d1cSJulian Grajkowski 	if (adf_cfg_add_fw_version(accel_dev)) {
46578ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
46678ee8d1cSJulian Grajkowski 			      "Failed to update configuration FW version\n");
46778ee8d1cSJulian Grajkowski 		return EFAULT;
46878ee8d1cSJulian Grajkowski 	}
46978ee8d1cSJulian Grajkowski 
47078ee8d1cSJulian Grajkowski 	if (hw_data->measure_clock)
47178ee8d1cSJulian Grajkowski 		hw_data->measure_clock(accel_dev);
47278ee8d1cSJulian Grajkowski 
47378ee8d1cSJulian Grajkowski 	/*
47478ee8d1cSJulian Grajkowski 	 * Set ssm watch dog timer for slice hang detection
47578ee8d1cSJulian Grajkowski 	 * Note! Not supported on devices older than C62x
47678ee8d1cSJulian Grajkowski 	 */
47778ee8d1cSJulian Grajkowski 	if (hw_data->set_ssm_wdtimer && hw_data->set_ssm_wdtimer(accel_dev)) {
47878ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
47978ee8d1cSJulian Grajkowski 			      "QAT: Failed to set ssm watch dog timer\n");
48078ee8d1cSJulian Grajkowski 		return EFAULT;
48178ee8d1cSJulian Grajkowski 	}
48278ee8d1cSJulian Grajkowski 
483266b0663SKrzysztof Zdziarski 	if (hw_data->int_timer_init && hw_data->int_timer_init(accel_dev)) {
484266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
485266b0663SKrzysztof Zdziarski 			      "Failed to init heartbeat interrupt timer\n");
486266b0663SKrzysztof Zdziarski 		return -EFAULT;
487266b0663SKrzysztof Zdziarski 	}
488266b0663SKrzysztof Zdziarski 
48978ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
49078ee8d1cSJulian Grajkowski 	{
49178ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
49278ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_START)) {
49378ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
49478ee8d1cSJulian Grajkowski 				      "Failed to start service %s\n",
49578ee8d1cSJulian Grajkowski 				      service->name);
49678ee8d1cSJulian Grajkowski 			return EFAULT;
49778ee8d1cSJulian Grajkowski 		}
49878ee8d1cSJulian Grajkowski 		set_bit(accel_dev->accel_id, service->start_status);
49978ee8d1cSJulian Grajkowski 	}
50078ee8d1cSJulian Grajkowski 
501266b0663SKrzysztof Zdziarski 	if (accel_dev->is_vf || !accel_dev->u1.pf.vf_info) {
502266b0663SKrzysztof Zdziarski 		/*Register UIO devices */
503266b0663SKrzysztof Zdziarski 		if (adf_uio_register(accel_dev)) {
504266b0663SKrzysztof Zdziarski 			adf_uio_remove(accel_dev);
505266b0663SKrzysztof Zdziarski 			device_printf(GET_DEV(accel_dev),
506266b0663SKrzysztof Zdziarski 				      "Failed to register UIO devices\n");
507266b0663SKrzysztof Zdziarski 			set_bit(ADF_STATUS_STARTING, &accel_dev->status);
508266b0663SKrzysztof Zdziarski 			clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
509266b0663SKrzysztof Zdziarski 			return ENODEV;
510266b0663SKrzysztof Zdziarski 		}
511266b0663SKrzysztof Zdziarski 	}
512266b0663SKrzysztof Zdziarski 
51378ee8d1cSJulian Grajkowski 	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status) &&
51478ee8d1cSJulian Grajkowski 	    adf_cfg_add_ext_params(accel_dev))
51578ee8d1cSJulian Grajkowski 		return EFAULT;
51678ee8d1cSJulian Grajkowski 
51778ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
51878ee8d1cSJulian Grajkowski 	set_bit(ADF_STATUS_STARTED, &accel_dev->status);
51978ee8d1cSJulian Grajkowski 
520c38bafeeSHareshx Sankar Raj 	adf_dbgfs_add(accel_dev);
521c38bafeeSHareshx Sankar Raj 
52278ee8d1cSJulian Grajkowski 	return 0;
52378ee8d1cSJulian Grajkowski }
52478ee8d1cSJulian Grajkowski 
52578ee8d1cSJulian Grajkowski /**
52678ee8d1cSJulian Grajkowski  * adf_dev_stop() - Stop acceleration service for the given accel device
52778ee8d1cSJulian Grajkowski  * @accel_dev:    Pointer to acceleration device.
52878ee8d1cSJulian Grajkowski  *
52978ee8d1cSJulian Grajkowski  * Function notifies all the registered services that the acceleration device
53078ee8d1cSJulian Grajkowski  * is shuting down.
53178ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
53278ee8d1cSJulian Grajkowski  *
53378ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
53478ee8d1cSJulian Grajkowski  */
53578ee8d1cSJulian Grajkowski int
adf_dev_stop(struct adf_accel_dev * accel_dev)53678ee8d1cSJulian Grajkowski adf_dev_stop(struct adf_accel_dev *accel_dev)
53778ee8d1cSJulian Grajkowski {
538*ded037e6SHareshx Sankar Raj 	int ret = 0;
539*ded037e6SHareshx Sankar Raj 
540*ded037e6SHareshx Sankar Raj 	mutex_lock(&accel_dev->lock);
541*ded037e6SHareshx Sankar Raj 	ret = adf_dev_stop_locked(accel_dev);
542*ded037e6SHareshx Sankar Raj 	mutex_unlock(&accel_dev->lock);
543*ded037e6SHareshx Sankar Raj 
544*ded037e6SHareshx Sankar Raj 	return ret;
545*ded037e6SHareshx Sankar Raj }
546*ded037e6SHareshx Sankar Raj 
547*ded037e6SHareshx Sankar Raj static int
adf_dev_stop_locked(struct adf_accel_dev * accel_dev)548*ded037e6SHareshx Sankar Raj adf_dev_stop_locked(struct adf_accel_dev *accel_dev)
549*ded037e6SHareshx Sankar Raj {
55078ee8d1cSJulian Grajkowski 	struct service_hndl *service;
55178ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
55278ee8d1cSJulian Grajkowski 
553*ded037e6SHareshx Sankar Raj 	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status))
554*ded037e6SHareshx Sankar Raj 		return 0;
555*ded037e6SHareshx Sankar Raj 
55678ee8d1cSJulian Grajkowski 	if (!adf_dev_started(accel_dev) &&
55778ee8d1cSJulian Grajkowski 	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) {
55878ee8d1cSJulian Grajkowski 		return 0;
55978ee8d1cSJulian Grajkowski 	}
56078ee8d1cSJulian Grajkowski 
56178ee8d1cSJulian Grajkowski 	if (adf_dev_stop_notify_sync(accel_dev)) {
56278ee8d1cSJulian Grajkowski 		device_printf(
56378ee8d1cSJulian Grajkowski 		    GET_DEV(accel_dev),
56478ee8d1cSJulian Grajkowski 		    "Waiting for device un-busy failed. Retries limit reached\n");
56578ee8d1cSJulian Grajkowski 		return EBUSY;
56678ee8d1cSJulian Grajkowski 	}
56778ee8d1cSJulian Grajkowski 
568c38bafeeSHareshx Sankar Raj 	adf_dbgfs_rm(accel_dev);
569c38bafeeSHareshx Sankar Raj 
57078ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
57178ee8d1cSJulian Grajkowski 	clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
57278ee8d1cSJulian Grajkowski 
573266b0663SKrzysztof Zdziarski 	if (accel_dev->hw_device->int_timer_exit)
574266b0663SKrzysztof Zdziarski 		accel_dev->hw_device->int_timer_exit(accel_dev);
575266b0663SKrzysztof Zdziarski 
57678ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
57778ee8d1cSJulian Grajkowski 	{
57878ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
57978ee8d1cSJulian Grajkowski 		if (!test_bit(accel_dev->accel_id, service->start_status))
58078ee8d1cSJulian Grajkowski 			continue;
58178ee8d1cSJulian Grajkowski 		clear_bit(accel_dev->accel_id, service->start_status);
58278ee8d1cSJulian Grajkowski 	}
58378ee8d1cSJulian Grajkowski 
584266b0663SKrzysztof Zdziarski 	if (accel_dev->is_vf || !accel_dev->u1.pf.vf_info) {
585266b0663SKrzysztof Zdziarski 		/* Remove UIO Devices */
586266b0663SKrzysztof Zdziarski 		adf_uio_remove(accel_dev);
587266b0663SKrzysztof Zdziarski 	}
588266b0663SKrzysztof Zdziarski 
58978ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) {
59078ee8d1cSJulian Grajkowski 		if (adf_ae_stop(accel_dev))
59178ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
59278ee8d1cSJulian Grajkowski 				      "failed to stop AE\n");
59378ee8d1cSJulian Grajkowski 		else
59478ee8d1cSJulian Grajkowski 			clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
59578ee8d1cSJulian Grajkowski 	}
59678ee8d1cSJulian Grajkowski 
59778ee8d1cSJulian Grajkowski 	return 0;
59878ee8d1cSJulian Grajkowski }
59978ee8d1cSJulian Grajkowski 
60078ee8d1cSJulian Grajkowski /**
60178ee8d1cSJulian Grajkowski  * adf_dev_shutdown() - shutdown acceleration services and data strucutures
60278ee8d1cSJulian Grajkowski  * @accel_dev: Pointer to acceleration device
60378ee8d1cSJulian Grajkowski  *
60478ee8d1cSJulian Grajkowski  * Cleanup the ring data structures and the admin comms and arbitration
60578ee8d1cSJulian Grajkowski  * services.
60678ee8d1cSJulian Grajkowski  */
60778ee8d1cSJulian Grajkowski void
adf_dev_shutdown(struct adf_accel_dev * accel_dev)60878ee8d1cSJulian Grajkowski adf_dev_shutdown(struct adf_accel_dev *accel_dev)
60978ee8d1cSJulian Grajkowski {
610*ded037e6SHareshx Sankar Raj 	mutex_lock(&accel_dev->lock);
611*ded037e6SHareshx Sankar Raj 	adf_dev_shutdown_locked(accel_dev);
612*ded037e6SHareshx Sankar Raj 	mutex_unlock(&accel_dev->lock);
613*ded037e6SHareshx Sankar Raj }
614*ded037e6SHareshx Sankar Raj 
615*ded037e6SHareshx Sankar Raj static void
adf_dev_shutdown_locked(struct adf_accel_dev * accel_dev)616*ded037e6SHareshx Sankar Raj adf_dev_shutdown_locked(struct adf_accel_dev *accel_dev)
617*ded037e6SHareshx Sankar Raj {
61878ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
61978ee8d1cSJulian Grajkowski 	struct service_hndl *service;
62078ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
62178ee8d1cSJulian Grajkowski 
622*ded037e6SHareshx Sankar Raj 	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status))
623*ded037e6SHareshx Sankar Raj 		return;
624*ded037e6SHareshx Sankar Raj 
62578ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, &accel_dev->status)) {
62678ee8d1cSJulian Grajkowski 		sysctl_ctx_free(&accel_dev->sysctl_ctx);
62778ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED,
62878ee8d1cSJulian Grajkowski 			  &accel_dev->status);
62978ee8d1cSJulian Grajkowski 	}
63078ee8d1cSJulian Grajkowski 
63178ee8d1cSJulian Grajkowski 	if (!hw_data) {
63278ee8d1cSJulian Grajkowski 		device_printf(
63378ee8d1cSJulian Grajkowski 		    GET_DEV(accel_dev),
63478ee8d1cSJulian Grajkowski 		    "QAT: Failed to shutdown device - hw_data not set\n");
63578ee8d1cSJulian Grajkowski 		return;
63678ee8d1cSJulian Grajkowski 	}
63778ee8d1cSJulian Grajkowski 
63878ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
63978ee8d1cSJulian Grajkowski 		adf_ae_fw_release(accel_dev);
64078ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
64178ee8d1cSJulian Grajkowski 	}
64278ee8d1cSJulian Grajkowski 
64378ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
64478ee8d1cSJulian Grajkowski 		if (adf_ae_shutdown(accel_dev))
64578ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
64678ee8d1cSJulian Grajkowski 				      "Failed to shutdown Accel Engine\n");
64778ee8d1cSJulian Grajkowski 		else
64878ee8d1cSJulian Grajkowski 			clear_bit(ADF_STATUS_AE_INITIALISED,
64978ee8d1cSJulian Grajkowski 				  &accel_dev->status);
65078ee8d1cSJulian Grajkowski 	}
65178ee8d1cSJulian Grajkowski 
65278ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
65378ee8d1cSJulian Grajkowski 	{
65478ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
65578ee8d1cSJulian Grajkowski 		if (!test_bit(accel_dev->accel_id, service->init_status))
65678ee8d1cSJulian Grajkowski 			continue;
65778ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
65878ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
65978ee8d1cSJulian Grajkowski 				      "Failed to shutdown service %s\n",
66078ee8d1cSJulian Grajkowski 				      service->name);
66178ee8d1cSJulian Grajkowski 		else
66278ee8d1cSJulian Grajkowski 			clear_bit(accel_dev->accel_id, service->init_status);
66378ee8d1cSJulian Grajkowski 	}
66478ee8d1cSJulian Grajkowski 
66578ee8d1cSJulian Grajkowski 	hw_data->disable_iov(accel_dev);
66678ee8d1cSJulian Grajkowski 
66778ee8d1cSJulian Grajkowski 	if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
66878ee8d1cSJulian Grajkowski 		hw_data->free_irq(accel_dev);
66978ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
67078ee8d1cSJulian Grajkowski 	}
67178ee8d1cSJulian Grajkowski 
67278ee8d1cSJulian Grajkowski 	/* Delete configuration only if not restarting */
673*ded037e6SHareshx Sankar Raj 	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) {
67478ee8d1cSJulian Grajkowski 		adf_cfg_del_all(accel_dev);
675*ded037e6SHareshx Sankar Raj #ifdef QAT_UIO
676*ded037e6SHareshx Sankar Raj 		adf_cfg_device_clear_all(accel_dev);
677*ded037e6SHareshx Sankar Raj #endif
678*ded037e6SHareshx Sankar Raj 	}
67978ee8d1cSJulian Grajkowski 
68078ee8d1cSJulian Grajkowski 	if (hw_data->remove_pke_stats)
68178ee8d1cSJulian Grajkowski 		hw_data->remove_pke_stats(accel_dev);
68278ee8d1cSJulian Grajkowski 
68378ee8d1cSJulian Grajkowski 	if (hw_data->remove_misc_error)
68478ee8d1cSJulian Grajkowski 		hw_data->remove_misc_error(accel_dev);
68578ee8d1cSJulian Grajkowski 
68678ee8d1cSJulian Grajkowski 	if (hw_data->exit_ras)
68778ee8d1cSJulian Grajkowski 		hw_data->exit_ras(accel_dev);
68878ee8d1cSJulian Grajkowski 
68978ee8d1cSJulian Grajkowski 	if (hw_data->exit_arb)
69078ee8d1cSJulian Grajkowski 		hw_data->exit_arb(accel_dev);
69178ee8d1cSJulian Grajkowski 
69278ee8d1cSJulian Grajkowski 	if (hw_data->exit_admin_comms)
69378ee8d1cSJulian Grajkowski 		hw_data->exit_admin_comms(accel_dev);
69478ee8d1cSJulian Grajkowski 
69578ee8d1cSJulian Grajkowski 	if (hw_data->exit_accel_units)
69678ee8d1cSJulian Grajkowski 		hw_data->exit_accel_units(accel_dev);
69778ee8d1cSJulian Grajkowski 
69878ee8d1cSJulian Grajkowski 	adf_cleanup_etr_data(accel_dev);
69978ee8d1cSJulian Grajkowski 	if (hw_data->restore_device)
70078ee8d1cSJulian Grajkowski 		hw_data->restore_device(accel_dev);
70178ee8d1cSJulian Grajkowski }
70278ee8d1cSJulian Grajkowski 
70378ee8d1cSJulian Grajkowski /**
70478ee8d1cSJulian Grajkowski  * adf_dev_reset() - Reset acceleration service for the given accel device
70578ee8d1cSJulian Grajkowski  * @accel_dev:    Pointer to acceleration device.
70678ee8d1cSJulian Grajkowski  * @mode: Specifies reset mode - synchronous or asynchronous.
70778ee8d1cSJulian Grajkowski  * Function notifies all the registered services that the acceleration device
70878ee8d1cSJulian Grajkowski  * is resetting.
70978ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
71078ee8d1cSJulian Grajkowski  *
71178ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
71278ee8d1cSJulian Grajkowski  */
71378ee8d1cSJulian Grajkowski int
adf_dev_reset(struct adf_accel_dev * accel_dev,enum adf_dev_reset_mode mode)71478ee8d1cSJulian Grajkowski adf_dev_reset(struct adf_accel_dev *accel_dev, enum adf_dev_reset_mode mode)
71578ee8d1cSJulian Grajkowski {
71678ee8d1cSJulian Grajkowski 	return adf_dev_aer_schedule_reset(accel_dev, mode);
71778ee8d1cSJulian Grajkowski }
71878ee8d1cSJulian Grajkowski 
71978ee8d1cSJulian Grajkowski int
adf_dev_restarting_notify(struct adf_accel_dev * accel_dev)72078ee8d1cSJulian Grajkowski adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
72178ee8d1cSJulian Grajkowski {
72278ee8d1cSJulian Grajkowski 	struct service_hndl *service;
72378ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
72478ee8d1cSJulian Grajkowski 
72578ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
72678ee8d1cSJulian Grajkowski 	{
72778ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
72878ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
72978ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
73078ee8d1cSJulian Grajkowski 				      "Failed to restart service %s.\n",
73178ee8d1cSJulian Grajkowski 				      service->name);
73278ee8d1cSJulian Grajkowski 	}
73378ee8d1cSJulian Grajkowski 	return 0;
73478ee8d1cSJulian Grajkowski }
73578ee8d1cSJulian Grajkowski 
73678ee8d1cSJulian Grajkowski int
adf_dev_restarting_notify_sync(struct adf_accel_dev * accel_dev)73778ee8d1cSJulian Grajkowski adf_dev_restarting_notify_sync(struct adf_accel_dev *accel_dev)
73878ee8d1cSJulian Grajkowski {
73978ee8d1cSJulian Grajkowski 	int times;
74078ee8d1cSJulian Grajkowski 
74178ee8d1cSJulian Grajkowski 	adf_dev_restarting_notify(accel_dev);
74278ee8d1cSJulian Grajkowski 	for (times = 0; times < ADF_STOP_RETRY; times++) {
74378ee8d1cSJulian Grajkowski 		if (!adf_dev_in_use(accel_dev))
74478ee8d1cSJulian Grajkowski 			break;
74578ee8d1cSJulian Grajkowski 		dev_dbg(GET_DEV(accel_dev), "retry times=%d\n", times);
74678ee8d1cSJulian Grajkowski 		pause_ms("adfstop", 100);
74778ee8d1cSJulian Grajkowski 	}
74878ee8d1cSJulian Grajkowski 	if (adf_dev_in_use(accel_dev)) {
74978ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
75078ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
75178ee8d1cSJulian Grajkowski 			      "Device still in use during reset sequence.\n");
75278ee8d1cSJulian Grajkowski 		return EBUSY;
75378ee8d1cSJulian Grajkowski 	}
75478ee8d1cSJulian Grajkowski 
75578ee8d1cSJulian Grajkowski 	return 0;
75678ee8d1cSJulian Grajkowski }
75778ee8d1cSJulian Grajkowski 
75878ee8d1cSJulian Grajkowski int
adf_dev_stop_notify_sync(struct adf_accel_dev * accel_dev)75978ee8d1cSJulian Grajkowski adf_dev_stop_notify_sync(struct adf_accel_dev *accel_dev)
76078ee8d1cSJulian Grajkowski {
76178ee8d1cSJulian Grajkowski 	int times;
76278ee8d1cSJulian Grajkowski 
76378ee8d1cSJulian Grajkowski 	struct service_hndl *service;
76478ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
76578ee8d1cSJulian Grajkowski 
76678ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
76778ee8d1cSJulian Grajkowski 	{
76878ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
76978ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_STOP))
77078ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
77178ee8d1cSJulian Grajkowski 				      "Failed to restart service %s.\n",
77278ee8d1cSJulian Grajkowski 				      service->name);
77378ee8d1cSJulian Grajkowski 	}
77478ee8d1cSJulian Grajkowski 
77578ee8d1cSJulian Grajkowski 	for (times = 0; times < ADF_STOP_RETRY; times++) {
77678ee8d1cSJulian Grajkowski 		if (!adf_dev_in_use(accel_dev))
77778ee8d1cSJulian Grajkowski 			break;
77878ee8d1cSJulian Grajkowski 		dev_dbg(GET_DEV(accel_dev), "retry times=%d\n", times);
77978ee8d1cSJulian Grajkowski 		pause_ms("adfstop", 100);
78078ee8d1cSJulian Grajkowski 	}
78178ee8d1cSJulian Grajkowski 	if (adf_dev_in_use(accel_dev)) {
78278ee8d1cSJulian Grajkowski 		clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
78378ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev),
78478ee8d1cSJulian Grajkowski 			      "Device still in use during stop sequence.\n");
78578ee8d1cSJulian Grajkowski 		return EBUSY;
78678ee8d1cSJulian Grajkowski 	}
78778ee8d1cSJulian Grajkowski 
78878ee8d1cSJulian Grajkowski 	return 0;
78978ee8d1cSJulian Grajkowski }
79078ee8d1cSJulian Grajkowski 
79178ee8d1cSJulian Grajkowski int
adf_dev_restarted_notify(struct adf_accel_dev * accel_dev)79278ee8d1cSJulian Grajkowski adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
79378ee8d1cSJulian Grajkowski {
79478ee8d1cSJulian Grajkowski 	struct service_hndl *service;
79578ee8d1cSJulian Grajkowski 	struct list_head *list_itr;
79678ee8d1cSJulian Grajkowski 
79778ee8d1cSJulian Grajkowski 	list_for_each(list_itr, &service_table)
79878ee8d1cSJulian Grajkowski 	{
79978ee8d1cSJulian Grajkowski 		service = list_entry(list_itr, struct service_hndl, list);
80078ee8d1cSJulian Grajkowski 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
80178ee8d1cSJulian Grajkowski 			device_printf(GET_DEV(accel_dev),
80278ee8d1cSJulian Grajkowski 				      "Failed to restart service %s.\n",
80378ee8d1cSJulian Grajkowski 				      service->name);
80478ee8d1cSJulian Grajkowski 	}
80578ee8d1cSJulian Grajkowski 	return 0;
80678ee8d1cSJulian Grajkowski }
807