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