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_transport_access_macros.h"
1278ee8d1cSJulian Grajkowski #include "adf_transport_internal.h"
1378ee8d1cSJulian Grajkowski #include <sys/firmware.h>
1478ee8d1cSJulian Grajkowski #include <dev/pci/pcivar.h>
1578ee8d1cSJulian Grajkowski #include "adf_cfg.h"
1678ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
1778ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
1878ee8d1cSJulian Grajkowski #include "icp_qat_uclo.h"
1978ee8d1cSJulian Grajkowski #include "icp_qat_hw.h"
2078ee8d1cSJulian Grajkowski
2178ee8d1cSJulian Grajkowski #define MMP_VERSION_LEN 4
2278ee8d1cSJulian Grajkowski
2378ee8d1cSJulian Grajkowski struct adf_mmp_version_s {
2478ee8d1cSJulian Grajkowski u8 ver_val[MMP_VERSION_LEN];
2578ee8d1cSJulian Grajkowski };
2678ee8d1cSJulian Grajkowski
2778ee8d1cSJulian Grajkowski static int
request_firmware(const struct firmware ** firmware_p,const char * name)2878ee8d1cSJulian Grajkowski request_firmware(const struct firmware **firmware_p, const char *name)
2978ee8d1cSJulian Grajkowski {
3078ee8d1cSJulian Grajkowski int retval = 0;
3178ee8d1cSJulian Grajkowski if (NULL == firmware_p) {
3278ee8d1cSJulian Grajkowski return -1;
3378ee8d1cSJulian Grajkowski }
3478ee8d1cSJulian Grajkowski *firmware_p = firmware_get(name);
3578ee8d1cSJulian Grajkowski if (NULL == *firmware_p) {
3678ee8d1cSJulian Grajkowski retval = -1;
3778ee8d1cSJulian Grajkowski }
3878ee8d1cSJulian Grajkowski return retval;
3978ee8d1cSJulian Grajkowski }
4078ee8d1cSJulian Grajkowski
4178ee8d1cSJulian Grajkowski int
adf_ae_fw_load(struct adf_accel_dev * accel_dev)4278ee8d1cSJulian Grajkowski adf_ae_fw_load(struct adf_accel_dev *accel_dev)
4378ee8d1cSJulian Grajkowski {
4478ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
4578ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_device = accel_dev->hw_device;
4678ee8d1cSJulian Grajkowski const void *fw_addr, *mmp_addr;
4778ee8d1cSJulian Grajkowski u32 fw_size, mmp_size;
4878ee8d1cSJulian Grajkowski s32 i = 0;
4978ee8d1cSJulian Grajkowski u32 max_objs = 1;
5078ee8d1cSJulian Grajkowski const char *obj_name = NULL;
5178ee8d1cSJulian Grajkowski struct adf_mmp_version_s mmp_ver = { { 0 } };
5278ee8d1cSJulian Grajkowski unsigned int cfg_ae_mask = 0;
5378ee8d1cSJulian Grajkowski
5478ee8d1cSJulian Grajkowski if (!hw_device->fw_name)
5578ee8d1cSJulian Grajkowski return 0;
5678ee8d1cSJulian Grajkowski
5778ee8d1cSJulian Grajkowski if (request_firmware(&loader_data->uof_fw, hw_device->fw_name)) {
5878ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
5978ee8d1cSJulian Grajkowski "Failed to load UOF FW %s\n",
6078ee8d1cSJulian Grajkowski hw_device->fw_name);
6178ee8d1cSJulian Grajkowski goto out_err;
6278ee8d1cSJulian Grajkowski }
6378ee8d1cSJulian Grajkowski
6478ee8d1cSJulian Grajkowski if (request_firmware(&loader_data->mmp_fw, hw_device->fw_mmp_name)) {
6578ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
6678ee8d1cSJulian Grajkowski "Failed to load MMP FW %s\n",
6778ee8d1cSJulian Grajkowski hw_device->fw_mmp_name);
6878ee8d1cSJulian Grajkowski goto out_err;
6978ee8d1cSJulian Grajkowski }
7078ee8d1cSJulian Grajkowski
7178ee8d1cSJulian Grajkowski fw_size = loader_data->uof_fw->datasize;
7278ee8d1cSJulian Grajkowski fw_addr = loader_data->uof_fw->data;
7378ee8d1cSJulian Grajkowski mmp_size = loader_data->mmp_fw->datasize;
7478ee8d1cSJulian Grajkowski mmp_addr = loader_data->mmp_fw->data;
7578ee8d1cSJulian Grajkowski
7678ee8d1cSJulian Grajkowski memcpy(&mmp_ver, mmp_addr, MMP_VERSION_LEN);
7778ee8d1cSJulian Grajkowski
7878ee8d1cSJulian Grajkowski accel_dev->fw_versions.mmp_version_major = mmp_ver.ver_val[0];
7978ee8d1cSJulian Grajkowski accel_dev->fw_versions.mmp_version_minor = mmp_ver.ver_val[1];
8078ee8d1cSJulian Grajkowski accel_dev->fw_versions.mmp_version_patch = mmp_ver.ver_val[2];
8178ee8d1cSJulian Grajkowski
8278ee8d1cSJulian Grajkowski if (hw_device->accel_capabilities_mask &
8378ee8d1cSJulian Grajkowski ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)
8478ee8d1cSJulian Grajkowski if (qat_uclo_wr_mimage(loader_data->fw_loader,
8578ee8d1cSJulian Grajkowski mmp_addr,
8678ee8d1cSJulian Grajkowski mmp_size)) {
8778ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
8878ee8d1cSJulian Grajkowski "Failed to load MMP\n");
8978ee8d1cSJulian Grajkowski goto out_err;
9078ee8d1cSJulian Grajkowski }
9178ee8d1cSJulian Grajkowski
9278ee8d1cSJulian Grajkowski if (hw_device->get_objs_num)
9378ee8d1cSJulian Grajkowski max_objs = hw_device->get_objs_num(accel_dev);
9478ee8d1cSJulian Grajkowski
9578ee8d1cSJulian Grajkowski for (i = max_objs - 1; i >= 0; i--) {
9678ee8d1cSJulian Grajkowski /* obj_name is used to indicate the firmware name in MOF,
9778ee8d1cSJulian Grajkowski * config unit0 must be loaded at end for authentication
9878ee8d1cSJulian Grajkowski */
9978ee8d1cSJulian Grajkowski if (hw_device->get_obj_name && hw_device->get_obj_cfg_ae_mask) {
10078ee8d1cSJulian Grajkowski unsigned long service_mask = hw_device->service_mask;
101*a977168cSMichal Gulbicki enum adf_accel_unit_services service_type =
102*a977168cSMichal Gulbicki ADF_ACCEL_SERVICE_NULL;
10378ee8d1cSJulian Grajkowski
104*a977168cSMichal Gulbicki if (hw_device->get_service_type)
105*a977168cSMichal Gulbicki service_type =
106*a977168cSMichal Gulbicki hw_device->get_service_type(accel_dev, i);
107*a977168cSMichal Gulbicki else
108*a977168cSMichal Gulbicki service_type = BIT(i);
109*a977168cSMichal Gulbicki
110*a977168cSMichal Gulbicki if (service_mask && !(service_mask & service_type))
11178ee8d1cSJulian Grajkowski continue;
112*a977168cSMichal Gulbicki
113*a977168cSMichal Gulbicki obj_name =
114*a977168cSMichal Gulbicki hw_device->get_obj_name(accel_dev, service_type);
115*a977168cSMichal Gulbicki cfg_ae_mask =
116*a977168cSMichal Gulbicki hw_device->get_obj_cfg_ae_mask(accel_dev,
117*a977168cSMichal Gulbicki service_type);
118*a977168cSMichal Gulbicki
11978ee8d1cSJulian Grajkowski if (!obj_name) {
12078ee8d1cSJulian Grajkowski device_printf(
12178ee8d1cSJulian Grajkowski GET_DEV(accel_dev),
12278ee8d1cSJulian Grajkowski "Invalid object (service = %lx)\n",
12378ee8d1cSJulian Grajkowski BIT(i));
12478ee8d1cSJulian Grajkowski goto out_err;
12578ee8d1cSJulian Grajkowski }
126*a977168cSMichal Gulbicki if (!cfg_ae_mask)
12778ee8d1cSJulian Grajkowski continue;
12878ee8d1cSJulian Grajkowski if (qat_uclo_set_cfg_ae_mask(loader_data->fw_loader,
12978ee8d1cSJulian Grajkowski cfg_ae_mask)) {
13078ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
13178ee8d1cSJulian Grajkowski "Invalid config AE mask\n");
13278ee8d1cSJulian Grajkowski goto out_err;
13378ee8d1cSJulian Grajkowski }
13478ee8d1cSJulian Grajkowski }
13578ee8d1cSJulian Grajkowski
13678ee8d1cSJulian Grajkowski if (qat_uclo_map_obj(
13778ee8d1cSJulian Grajkowski loader_data->fw_loader, fw_addr, fw_size, obj_name)) {
13878ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
13978ee8d1cSJulian Grajkowski "Failed to map UOF firmware\n");
14078ee8d1cSJulian Grajkowski goto out_err;
14178ee8d1cSJulian Grajkowski }
14278ee8d1cSJulian Grajkowski if (qat_uclo_wr_all_uimage(loader_data->fw_loader)) {
14378ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
14478ee8d1cSJulian Grajkowski "Failed to load UOF firmware\n");
14578ee8d1cSJulian Grajkowski goto out_err;
14678ee8d1cSJulian Grajkowski }
14778ee8d1cSJulian Grajkowski qat_uclo_del_obj(loader_data->fw_loader);
14878ee8d1cSJulian Grajkowski obj_name = NULL;
14978ee8d1cSJulian Grajkowski }
15078ee8d1cSJulian Grajkowski
15178ee8d1cSJulian Grajkowski return 0;
15278ee8d1cSJulian Grajkowski
15378ee8d1cSJulian Grajkowski out_err:
15478ee8d1cSJulian Grajkowski adf_ae_fw_release(accel_dev);
15578ee8d1cSJulian Grajkowski return EFAULT;
15678ee8d1cSJulian Grajkowski }
15778ee8d1cSJulian Grajkowski
15878ee8d1cSJulian Grajkowski void
adf_ae_fw_release(struct adf_accel_dev * accel_dev)15978ee8d1cSJulian Grajkowski adf_ae_fw_release(struct adf_accel_dev *accel_dev)
16078ee8d1cSJulian Grajkowski {
16178ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
16278ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_device = accel_dev->hw_device;
16378ee8d1cSJulian Grajkowski
16478ee8d1cSJulian Grajkowski if (!hw_device->fw_name)
16578ee8d1cSJulian Grajkowski return;
16678ee8d1cSJulian Grajkowski if (loader_data->fw_loader)
16778ee8d1cSJulian Grajkowski qat_uclo_del_obj(loader_data->fw_loader);
16878ee8d1cSJulian Grajkowski if (loader_data->fw_loader && loader_data->fw_loader->mobj_handle)
16978ee8d1cSJulian Grajkowski qat_uclo_del_mof(loader_data->fw_loader);
17078ee8d1cSJulian Grajkowski qat_hal_deinit(loader_data->fw_loader);
17178ee8d1cSJulian Grajkowski if (loader_data->uof_fw)
17278ee8d1cSJulian Grajkowski firmware_put(loader_data->uof_fw, FIRMWARE_UNLOAD);
17378ee8d1cSJulian Grajkowski if (loader_data->mmp_fw)
17478ee8d1cSJulian Grajkowski firmware_put(loader_data->mmp_fw, FIRMWARE_UNLOAD);
17578ee8d1cSJulian Grajkowski loader_data->uof_fw = NULL;
17678ee8d1cSJulian Grajkowski loader_data->mmp_fw = NULL;
17778ee8d1cSJulian Grajkowski loader_data->fw_loader = NULL;
17878ee8d1cSJulian Grajkowski }
17978ee8d1cSJulian Grajkowski
18078ee8d1cSJulian Grajkowski int
adf_ae_start(struct adf_accel_dev * accel_dev)18178ee8d1cSJulian Grajkowski adf_ae_start(struct adf_accel_dev *accel_dev)
18278ee8d1cSJulian Grajkowski {
18378ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
18478ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
185*a977168cSMichal Gulbicki uint32_t ae_ctr;
18678ee8d1cSJulian Grajkowski
18778ee8d1cSJulian Grajkowski if (!hw_data->fw_name)
18878ee8d1cSJulian Grajkowski return 0;
18978ee8d1cSJulian Grajkowski
190*a977168cSMichal Gulbicki ae_ctr = qat_hal_start(loader_data->fw_loader);
19178ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
19278ee8d1cSJulian Grajkowski "qat_dev%d started %d acceleration engines\n",
19378ee8d1cSJulian Grajkowski accel_dev->accel_id,
19478ee8d1cSJulian Grajkowski ae_ctr);
19578ee8d1cSJulian Grajkowski return 0;
19678ee8d1cSJulian Grajkowski }
19778ee8d1cSJulian Grajkowski
19878ee8d1cSJulian Grajkowski int
adf_ae_stop(struct adf_accel_dev * accel_dev)19978ee8d1cSJulian Grajkowski adf_ae_stop(struct adf_accel_dev *accel_dev)
20078ee8d1cSJulian Grajkowski {
20178ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
20278ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
20378ee8d1cSJulian Grajkowski uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
20478ee8d1cSJulian Grajkowski
20578ee8d1cSJulian Grajkowski if (!hw_data->fw_name)
20678ee8d1cSJulian Grajkowski return 0;
20778ee8d1cSJulian Grajkowski
20878ee8d1cSJulian Grajkowski for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
20978ee8d1cSJulian Grajkowski if (hw_data->ae_mask & (1 << ae)) {
21078ee8d1cSJulian Grajkowski qat_hal_stop(loader_data->fw_loader, ae, 0xFF);
21178ee8d1cSJulian Grajkowski ae_ctr++;
21278ee8d1cSJulian Grajkowski }
21378ee8d1cSJulian Grajkowski }
21478ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
21578ee8d1cSJulian Grajkowski "qat_dev%d stopped %d acceleration engines\n",
21678ee8d1cSJulian Grajkowski accel_dev->accel_id,
21778ee8d1cSJulian Grajkowski ae_ctr);
21878ee8d1cSJulian Grajkowski return 0;
21978ee8d1cSJulian Grajkowski }
22078ee8d1cSJulian Grajkowski
22178ee8d1cSJulian Grajkowski static int
adf_ae_reset(struct adf_accel_dev * accel_dev,int ae)22278ee8d1cSJulian Grajkowski adf_ae_reset(struct adf_accel_dev *accel_dev, int ae)
22378ee8d1cSJulian Grajkowski {
22478ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
22578ee8d1cSJulian Grajkowski
22678ee8d1cSJulian Grajkowski qat_hal_reset(loader_data->fw_loader);
22778ee8d1cSJulian Grajkowski if (qat_hal_clr_reset(loader_data->fw_loader))
22878ee8d1cSJulian Grajkowski return EFAULT;
22978ee8d1cSJulian Grajkowski
23078ee8d1cSJulian Grajkowski return 0;
23178ee8d1cSJulian Grajkowski }
23278ee8d1cSJulian Grajkowski
23378ee8d1cSJulian Grajkowski int
adf_ae_init(struct adf_accel_dev * accel_dev)23478ee8d1cSJulian Grajkowski adf_ae_init(struct adf_accel_dev *accel_dev)
23578ee8d1cSJulian Grajkowski {
23678ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data;
23778ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_device = accel_dev->hw_device;
23878ee8d1cSJulian Grajkowski
23978ee8d1cSJulian Grajkowski if (!hw_device->fw_name)
24078ee8d1cSJulian Grajkowski return 0;
24178ee8d1cSJulian Grajkowski
24278ee8d1cSJulian Grajkowski loader_data = malloc(sizeof(*loader_data), M_QAT, M_WAITOK | M_ZERO);
24378ee8d1cSJulian Grajkowski
24478ee8d1cSJulian Grajkowski accel_dev->fw_loader = loader_data;
24578ee8d1cSJulian Grajkowski if (qat_hal_init(accel_dev)) {
24678ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev), "Failed to init the AEs\n");
24778ee8d1cSJulian Grajkowski free(loader_data, M_QAT);
24878ee8d1cSJulian Grajkowski return EFAULT;
24978ee8d1cSJulian Grajkowski }
25078ee8d1cSJulian Grajkowski if (adf_ae_reset(accel_dev, 0)) {
25178ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev), "Failed to reset the AEs\n");
25278ee8d1cSJulian Grajkowski qat_hal_deinit(loader_data->fw_loader);
25378ee8d1cSJulian Grajkowski free(loader_data, M_QAT);
25478ee8d1cSJulian Grajkowski return EFAULT;
25578ee8d1cSJulian Grajkowski }
25678ee8d1cSJulian Grajkowski return 0;
25778ee8d1cSJulian Grajkowski }
25878ee8d1cSJulian Grajkowski
25978ee8d1cSJulian Grajkowski int
adf_ae_shutdown(struct adf_accel_dev * accel_dev)26078ee8d1cSJulian Grajkowski adf_ae_shutdown(struct adf_accel_dev *accel_dev)
26178ee8d1cSJulian Grajkowski {
26278ee8d1cSJulian Grajkowski struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
26378ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_device = accel_dev->hw_device;
26478ee8d1cSJulian Grajkowski
26578ee8d1cSJulian Grajkowski if (!hw_device->fw_name)
26678ee8d1cSJulian Grajkowski return 0;
26778ee8d1cSJulian Grajkowski
26878ee8d1cSJulian Grajkowski qat_hal_deinit(loader_data->fw_loader);
26978ee8d1cSJulian Grajkowski free(accel_dev->fw_loader, M_QAT);
27078ee8d1cSJulian Grajkowski accel_dev->fw_loader = NULL;
27178ee8d1cSJulian Grajkowski return 0;
27278ee8d1cSJulian Grajkowski }
273