18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
28c2ecf20Sopenharmony_ci/* Copyright(c) 2014 - 2020 Intel Corporation */
38c2ecf20Sopenharmony_ci#include <linux/slab.h>
48c2ecf20Sopenharmony_ci#include <linux/ctype.h>
58c2ecf20Sopenharmony_ci#include <linux/kernel.h>
68c2ecf20Sopenharmony_ci#include <linux/delay.h>
78c2ecf20Sopenharmony_ci#include <linux/pci_ids.h>
88c2ecf20Sopenharmony_ci#include "adf_accel_devices.h"
98c2ecf20Sopenharmony_ci#include "adf_common_drv.h"
108c2ecf20Sopenharmony_ci#include "icp_qat_uclo.h"
118c2ecf20Sopenharmony_ci#include "icp_qat_hal.h"
128c2ecf20Sopenharmony_ci#include "icp_qat_fw_loader_handle.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define UWORD_CPYBUF_SIZE 1024
158c2ecf20Sopenharmony_ci#define INVLD_UWORD 0xffffffffffull
168c2ecf20Sopenharmony_ci#define PID_MINOR_REV 0xf
178c2ecf20Sopenharmony_ci#define PID_MAJOR_REV (0xf << 4)
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic int qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle *obj_handle,
208c2ecf20Sopenharmony_ci				 unsigned int ae, unsigned int image_num)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	struct icp_qat_uclo_aedata *ae_data;
238c2ecf20Sopenharmony_ci	struct icp_qat_uclo_encapme *encap_image;
248c2ecf20Sopenharmony_ci	struct icp_qat_uclo_page *page = NULL;
258c2ecf20Sopenharmony_ci	struct icp_qat_uclo_aeslice *ae_slice = NULL;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	ae_data = &obj_handle->ae_data[ae];
288c2ecf20Sopenharmony_ci	encap_image = &obj_handle->ae_uimage[image_num];
298c2ecf20Sopenharmony_ci	ae_slice = &ae_data->ae_slices[ae_data->slice_num];
308c2ecf20Sopenharmony_ci	ae_slice->encap_image = encap_image;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	if (encap_image->img_ptr) {
338c2ecf20Sopenharmony_ci		ae_slice->ctx_mask_assigned =
348c2ecf20Sopenharmony_ci					encap_image->img_ptr->ctx_assigned;
358c2ecf20Sopenharmony_ci		ae_data->eff_ustore_size = obj_handle->ustore_phy_size;
368c2ecf20Sopenharmony_ci	} else {
378c2ecf20Sopenharmony_ci		ae_slice->ctx_mask_assigned = 0;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci	ae_slice->region = kzalloc(sizeof(*ae_slice->region), GFP_KERNEL);
408c2ecf20Sopenharmony_ci	if (!ae_slice->region)
418c2ecf20Sopenharmony_ci		return -ENOMEM;
428c2ecf20Sopenharmony_ci	ae_slice->page = kzalloc(sizeof(*ae_slice->page), GFP_KERNEL);
438c2ecf20Sopenharmony_ci	if (!ae_slice->page)
448c2ecf20Sopenharmony_ci		goto out_err;
458c2ecf20Sopenharmony_ci	page = ae_slice->page;
468c2ecf20Sopenharmony_ci	page->encap_page = encap_image->page;
478c2ecf20Sopenharmony_ci	ae_slice->page->region = ae_slice->region;
488c2ecf20Sopenharmony_ci	ae_data->slice_num++;
498c2ecf20Sopenharmony_ci	return 0;
508c2ecf20Sopenharmony_ciout_err:
518c2ecf20Sopenharmony_ci	kfree(ae_slice->region);
528c2ecf20Sopenharmony_ci	ae_slice->region = NULL;
538c2ecf20Sopenharmony_ci	return -ENOMEM;
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic int qat_uclo_free_ae_data(struct icp_qat_uclo_aedata *ae_data)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	unsigned int i;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	if (!ae_data) {
618c2ecf20Sopenharmony_ci		pr_err("QAT: bad argument, ae_data is NULL\n ");
628c2ecf20Sopenharmony_ci		return -EINVAL;
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	for (i = 0; i < ae_data->slice_num; i++) {
668c2ecf20Sopenharmony_ci		kfree(ae_data->ae_slices[i].region);
678c2ecf20Sopenharmony_ci		ae_data->ae_slices[i].region = NULL;
688c2ecf20Sopenharmony_ci		kfree(ae_data->ae_slices[i].page);
698c2ecf20Sopenharmony_ci		ae_data->ae_slices[i].page = NULL;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci	return 0;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic char *qat_uclo_get_string(struct icp_qat_uof_strtable *str_table,
758c2ecf20Sopenharmony_ci				 unsigned int str_offset)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	if ((!str_table->table_len) || (str_offset > str_table->table_len))
788c2ecf20Sopenharmony_ci		return NULL;
798c2ecf20Sopenharmony_ci	return (char *)(((uintptr_t)(str_table->strings)) + str_offset);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic int qat_uclo_check_uof_format(struct icp_qat_uof_filehdr *hdr)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	int maj = hdr->maj_ver & 0xff;
858c2ecf20Sopenharmony_ci	int min = hdr->min_ver & 0xff;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (hdr->file_id != ICP_QAT_UOF_FID) {
888c2ecf20Sopenharmony_ci		pr_err("QAT: Invalid header 0x%x\n", hdr->file_id);
898c2ecf20Sopenharmony_ci		return -EINVAL;
908c2ecf20Sopenharmony_ci	}
918c2ecf20Sopenharmony_ci	if (min != ICP_QAT_UOF_MINVER || maj != ICP_QAT_UOF_MAJVER) {
928c2ecf20Sopenharmony_ci		pr_err("QAT: bad UOF version, major 0x%x, minor 0x%x\n",
938c2ecf20Sopenharmony_ci		       maj, min);
948c2ecf20Sopenharmony_ci		return -EINVAL;
958c2ecf20Sopenharmony_ci	}
968c2ecf20Sopenharmony_ci	return 0;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic int qat_uclo_check_suof_format(struct icp_qat_suof_filehdr *suof_hdr)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	int maj = suof_hdr->maj_ver & 0xff;
1028c2ecf20Sopenharmony_ci	int min = suof_hdr->min_ver & 0xff;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (suof_hdr->file_id != ICP_QAT_SUOF_FID) {
1058c2ecf20Sopenharmony_ci		pr_err("QAT: invalid header 0x%x\n", suof_hdr->file_id);
1068c2ecf20Sopenharmony_ci		return -EINVAL;
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci	if (suof_hdr->fw_type != 0) {
1098c2ecf20Sopenharmony_ci		pr_err("QAT: unsupported firmware type\n");
1108c2ecf20Sopenharmony_ci		return -EINVAL;
1118c2ecf20Sopenharmony_ci	}
1128c2ecf20Sopenharmony_ci	if (suof_hdr->num_chunks <= 0x1) {
1138c2ecf20Sopenharmony_ci		pr_err("QAT: SUOF chunk amount is incorrect\n");
1148c2ecf20Sopenharmony_ci		return -EINVAL;
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci	if (maj != ICP_QAT_SUOF_MAJVER || min != ICP_QAT_SUOF_MINVER) {
1178c2ecf20Sopenharmony_ci		pr_err("QAT: bad SUOF version, major 0x%x, minor 0x%x\n",
1188c2ecf20Sopenharmony_ci		       maj, min);
1198c2ecf20Sopenharmony_ci		return -EINVAL;
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci	return 0;
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic void qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle *handle,
1258c2ecf20Sopenharmony_ci				      unsigned int addr, unsigned int *val,
1268c2ecf20Sopenharmony_ci				      unsigned int num_in_bytes)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	unsigned int outval;
1298c2ecf20Sopenharmony_ci	unsigned char *ptr = (unsigned char *)val;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	while (num_in_bytes) {
1328c2ecf20Sopenharmony_ci		memcpy(&outval, ptr, 4);
1338c2ecf20Sopenharmony_ci		SRAM_WRITE(handle, addr, outval);
1348c2ecf20Sopenharmony_ci		num_in_bytes -= 4;
1358c2ecf20Sopenharmony_ci		ptr += 4;
1368c2ecf20Sopenharmony_ci		addr += 4;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic void qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle *handle,
1418c2ecf20Sopenharmony_ci				      unsigned char ae, unsigned int addr,
1428c2ecf20Sopenharmony_ci				      unsigned int *val,
1438c2ecf20Sopenharmony_ci				      unsigned int num_in_bytes)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	unsigned int outval;
1468c2ecf20Sopenharmony_ci	unsigned char *ptr = (unsigned char *)val;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	addr >>= 0x2; /* convert to uword address */
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	while (num_in_bytes) {
1518c2ecf20Sopenharmony_ci		memcpy(&outval, ptr, 4);
1528c2ecf20Sopenharmony_ci		qat_hal_wr_umem(handle, ae, addr++, 1, &outval);
1538c2ecf20Sopenharmony_ci		num_in_bytes -= 4;
1548c2ecf20Sopenharmony_ci		ptr += 4;
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic void qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle *handle,
1598c2ecf20Sopenharmony_ci				   unsigned char ae,
1608c2ecf20Sopenharmony_ci				   struct icp_qat_uof_batch_init
1618c2ecf20Sopenharmony_ci				   *umem_init_header)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	struct icp_qat_uof_batch_init *umem_init;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (!umem_init_header)
1668c2ecf20Sopenharmony_ci		return;
1678c2ecf20Sopenharmony_ci	umem_init = umem_init_header->next;
1688c2ecf20Sopenharmony_ci	while (umem_init) {
1698c2ecf20Sopenharmony_ci		unsigned int addr, *value, size;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci		ae = umem_init->ae;
1728c2ecf20Sopenharmony_ci		addr = umem_init->addr;
1738c2ecf20Sopenharmony_ci		value = umem_init->value;
1748c2ecf20Sopenharmony_ci		size = umem_init->size;
1758c2ecf20Sopenharmony_ci		qat_uclo_wr_umem_by_words(handle, ae, addr, value, size);
1768c2ecf20Sopenharmony_ci		umem_init = umem_init->next;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic void
1818c2ecf20Sopenharmony_ciqat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,
1828c2ecf20Sopenharmony_ci				 struct icp_qat_uof_batch_init **base)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct icp_qat_uof_batch_init *umem_init;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	umem_init = *base;
1878c2ecf20Sopenharmony_ci	while (umem_init) {
1888c2ecf20Sopenharmony_ci		struct icp_qat_uof_batch_init *pre;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci		pre = umem_init;
1918c2ecf20Sopenharmony_ci		umem_init = umem_init->next;
1928c2ecf20Sopenharmony_ci		kfree(pre);
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci	*base = NULL;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic int qat_uclo_parse_num(char *str, unsigned int *num)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	char buf[16] = {0};
2008c2ecf20Sopenharmony_ci	unsigned long ae = 0;
2018c2ecf20Sopenharmony_ci	int i;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	strncpy(buf, str, 15);
2048c2ecf20Sopenharmony_ci	for (i = 0; i < 16; i++) {
2058c2ecf20Sopenharmony_ci		if (!isdigit(buf[i])) {
2068c2ecf20Sopenharmony_ci			buf[i] = '\0';
2078c2ecf20Sopenharmony_ci			break;
2088c2ecf20Sopenharmony_ci		}
2098c2ecf20Sopenharmony_ci	}
2108c2ecf20Sopenharmony_ci	if ((kstrtoul(buf, 10, &ae)))
2118c2ecf20Sopenharmony_ci		return -EFAULT;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	*num = (unsigned int)ae;
2148c2ecf20Sopenharmony_ci	return 0;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic int qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle *handle,
2188c2ecf20Sopenharmony_ci				     struct icp_qat_uof_initmem *init_mem,
2198c2ecf20Sopenharmony_ci				     unsigned int size_range, unsigned int *ae)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
2228c2ecf20Sopenharmony_ci	char *str;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if ((init_mem->addr + init_mem->num_in_bytes) > (size_range << 0x2)) {
2258c2ecf20Sopenharmony_ci		pr_err("QAT: initmem is out of range");
2268c2ecf20Sopenharmony_ci		return -EINVAL;
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci	if (init_mem->scope != ICP_QAT_UOF_LOCAL_SCOPE) {
2298c2ecf20Sopenharmony_ci		pr_err("QAT: Memory scope for init_mem error\n");
2308c2ecf20Sopenharmony_ci		return -EINVAL;
2318c2ecf20Sopenharmony_ci	}
2328c2ecf20Sopenharmony_ci	str = qat_uclo_get_string(&obj_handle->str_table, init_mem->sym_name);
2338c2ecf20Sopenharmony_ci	if (!str) {
2348c2ecf20Sopenharmony_ci		pr_err("QAT: AE name assigned in UOF init table is NULL\n");
2358c2ecf20Sopenharmony_ci		return -EINVAL;
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci	if (qat_uclo_parse_num(str, ae)) {
2388c2ecf20Sopenharmony_ci		pr_err("QAT: Parse num for AE number failed\n");
2398c2ecf20Sopenharmony_ci		return -EINVAL;
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci	if (*ae >= ICP_QAT_UCLO_MAX_AE) {
2428c2ecf20Sopenharmony_ci		pr_err("QAT: ae %d out of range\n", *ae);
2438c2ecf20Sopenharmony_ci		return -EINVAL;
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci	return 0;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic int qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle
2498c2ecf20Sopenharmony_ci					   *handle, struct icp_qat_uof_initmem
2508c2ecf20Sopenharmony_ci					   *init_mem, unsigned int ae,
2518c2ecf20Sopenharmony_ci					   struct icp_qat_uof_batch_init
2528c2ecf20Sopenharmony_ci					   **init_tab_base)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	struct icp_qat_uof_batch_init *init_header, *tail;
2558c2ecf20Sopenharmony_ci	struct icp_qat_uof_batch_init *mem_init, *tail_old;
2568c2ecf20Sopenharmony_ci	struct icp_qat_uof_memvar_attr *mem_val_attr;
2578c2ecf20Sopenharmony_ci	unsigned int i, flag = 0;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	mem_val_attr =
2608c2ecf20Sopenharmony_ci		(struct icp_qat_uof_memvar_attr *)((uintptr_t)init_mem +
2618c2ecf20Sopenharmony_ci		sizeof(struct icp_qat_uof_initmem));
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	init_header = *init_tab_base;
2648c2ecf20Sopenharmony_ci	if (!init_header) {
2658c2ecf20Sopenharmony_ci		init_header = kzalloc(sizeof(*init_header), GFP_KERNEL);
2668c2ecf20Sopenharmony_ci		if (!init_header)
2678c2ecf20Sopenharmony_ci			return -ENOMEM;
2688c2ecf20Sopenharmony_ci		init_header->size = 1;
2698c2ecf20Sopenharmony_ci		*init_tab_base = init_header;
2708c2ecf20Sopenharmony_ci		flag = 1;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci	tail_old = init_header;
2738c2ecf20Sopenharmony_ci	while (tail_old->next)
2748c2ecf20Sopenharmony_ci		tail_old = tail_old->next;
2758c2ecf20Sopenharmony_ci	tail = tail_old;
2768c2ecf20Sopenharmony_ci	for (i = 0; i < init_mem->val_attr_num; i++) {
2778c2ecf20Sopenharmony_ci		mem_init = kzalloc(sizeof(*mem_init), GFP_KERNEL);
2788c2ecf20Sopenharmony_ci		if (!mem_init)
2798c2ecf20Sopenharmony_ci			goto out_err;
2808c2ecf20Sopenharmony_ci		mem_init->ae = ae;
2818c2ecf20Sopenharmony_ci		mem_init->addr = init_mem->addr + mem_val_attr->offset_in_byte;
2828c2ecf20Sopenharmony_ci		mem_init->value = &mem_val_attr->value;
2838c2ecf20Sopenharmony_ci		mem_init->size = 4;
2848c2ecf20Sopenharmony_ci		mem_init->next = NULL;
2858c2ecf20Sopenharmony_ci		tail->next = mem_init;
2868c2ecf20Sopenharmony_ci		tail = mem_init;
2878c2ecf20Sopenharmony_ci		init_header->size += qat_hal_get_ins_num();
2888c2ecf20Sopenharmony_ci		mem_val_attr++;
2898c2ecf20Sopenharmony_ci	}
2908c2ecf20Sopenharmony_ci	return 0;
2918c2ecf20Sopenharmony_ciout_err:
2928c2ecf20Sopenharmony_ci	/* Do not free the list head unless we allocated it. */
2938c2ecf20Sopenharmony_ci	tail_old = tail_old->next;
2948c2ecf20Sopenharmony_ci	if (flag) {
2958c2ecf20Sopenharmony_ci		kfree(*init_tab_base);
2968c2ecf20Sopenharmony_ci		*init_tab_base = NULL;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	while (tail_old) {
3008c2ecf20Sopenharmony_ci		mem_init = tail_old->next;
3018c2ecf20Sopenharmony_ci		kfree(tail_old);
3028c2ecf20Sopenharmony_ci		tail_old = mem_init;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci	return -ENOMEM;
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic int qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle *handle,
3088c2ecf20Sopenharmony_ci				  struct icp_qat_uof_initmem *init_mem)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
3118c2ecf20Sopenharmony_ci	unsigned int ae;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	if (qat_uclo_fetch_initmem_ae(handle, init_mem,
3148c2ecf20Sopenharmony_ci				      ICP_QAT_UCLO_MAX_LMEM_REG, &ae))
3158c2ecf20Sopenharmony_ci		return -EINVAL;
3168c2ecf20Sopenharmony_ci	if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
3178c2ecf20Sopenharmony_ci					    &obj_handle->lm_init_tab[ae]))
3188c2ecf20Sopenharmony_ci		return -EINVAL;
3198c2ecf20Sopenharmony_ci	return 0;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
3238c2ecf20Sopenharmony_ci				  struct icp_qat_uof_initmem *init_mem)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
3268c2ecf20Sopenharmony_ci	unsigned int ae, ustore_size, uaddr, i;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	ustore_size = obj_handle->ustore_phy_size;
3298c2ecf20Sopenharmony_ci	if (qat_uclo_fetch_initmem_ae(handle, init_mem, ustore_size, &ae))
3308c2ecf20Sopenharmony_ci		return -EINVAL;
3318c2ecf20Sopenharmony_ci	if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
3328c2ecf20Sopenharmony_ci					    &obj_handle->umem_init_tab[ae]))
3338c2ecf20Sopenharmony_ci		return -EINVAL;
3348c2ecf20Sopenharmony_ci	/* set the highest ustore address referenced */
3358c2ecf20Sopenharmony_ci	uaddr = (init_mem->addr + init_mem->num_in_bytes) >> 0x2;
3368c2ecf20Sopenharmony_ci	for (i = 0; i < obj_handle->ae_data[ae].slice_num; i++) {
3378c2ecf20Sopenharmony_ci		if (obj_handle->ae_data[ae].ae_slices[i].
3388c2ecf20Sopenharmony_ci		    encap_image->uwords_num < uaddr)
3398c2ecf20Sopenharmony_ci			obj_handle->ae_data[ae].ae_slices[i].
3408c2ecf20Sopenharmony_ci			encap_image->uwords_num = uaddr;
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci	return 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
3468c2ecf20Sopenharmony_ci				   struct icp_qat_uof_initmem *init_mem)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	switch (init_mem->region) {
3498c2ecf20Sopenharmony_ci	case ICP_QAT_UOF_LMEM_REGION:
3508c2ecf20Sopenharmony_ci		if (qat_uclo_init_lmem_seg(handle, init_mem))
3518c2ecf20Sopenharmony_ci			return -EINVAL;
3528c2ecf20Sopenharmony_ci		break;
3538c2ecf20Sopenharmony_ci	case ICP_QAT_UOF_UMEM_REGION:
3548c2ecf20Sopenharmony_ci		if (qat_uclo_init_umem_seg(handle, init_mem))
3558c2ecf20Sopenharmony_ci			return -EINVAL;
3568c2ecf20Sopenharmony_ci		break;
3578c2ecf20Sopenharmony_ci	default:
3588c2ecf20Sopenharmony_ci		pr_err("QAT: initmem region error. region type=0x%x\n",
3598c2ecf20Sopenharmony_ci		       init_mem->region);
3608c2ecf20Sopenharmony_ci		return -EINVAL;
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci	return 0;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cistatic int qat_uclo_init_ustore(struct icp_qat_fw_loader_handle *handle,
3668c2ecf20Sopenharmony_ci				struct icp_qat_uclo_encapme *image)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	unsigned int i;
3698c2ecf20Sopenharmony_ci	struct icp_qat_uclo_encap_page *page;
3708c2ecf20Sopenharmony_ci	struct icp_qat_uof_image *uof_image;
3718c2ecf20Sopenharmony_ci	unsigned char ae;
3728c2ecf20Sopenharmony_ci	unsigned int ustore_size;
3738c2ecf20Sopenharmony_ci	unsigned int patt_pos;
3748c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
3758c2ecf20Sopenharmony_ci	u64 *fill_data;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	uof_image = image->img_ptr;
3788c2ecf20Sopenharmony_ci	fill_data = kcalloc(ICP_QAT_UCLO_MAX_USTORE, sizeof(u64),
3798c2ecf20Sopenharmony_ci			    GFP_KERNEL);
3808c2ecf20Sopenharmony_ci	if (!fill_data)
3818c2ecf20Sopenharmony_ci		return -ENOMEM;
3828c2ecf20Sopenharmony_ci	for (i = 0; i < ICP_QAT_UCLO_MAX_USTORE; i++)
3838c2ecf20Sopenharmony_ci		memcpy(&fill_data[i], &uof_image->fill_pattern,
3848c2ecf20Sopenharmony_ci		       sizeof(u64));
3858c2ecf20Sopenharmony_ci	page = image->page;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
3888c2ecf20Sopenharmony_ci		if (!test_bit(ae, (unsigned long *)&uof_image->ae_assigned))
3898c2ecf20Sopenharmony_ci			continue;
3908c2ecf20Sopenharmony_ci		ustore_size = obj_handle->ae_data[ae].eff_ustore_size;
3918c2ecf20Sopenharmony_ci		patt_pos = page->beg_addr_p + page->micro_words_num;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci		qat_hal_wr_uwords(handle, (unsigned char)ae, 0,
3948c2ecf20Sopenharmony_ci				  page->beg_addr_p, &fill_data[0]);
3958c2ecf20Sopenharmony_ci		qat_hal_wr_uwords(handle, (unsigned char)ae, patt_pos,
3968c2ecf20Sopenharmony_ci				  ustore_size - patt_pos + 1,
3978c2ecf20Sopenharmony_ci				  &fill_data[page->beg_addr_p]);
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci	kfree(fill_data);
4008c2ecf20Sopenharmony_ci	return 0;
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistatic int qat_uclo_init_memory(struct icp_qat_fw_loader_handle *handle)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	int i, ae;
4068c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
4078c2ecf20Sopenharmony_ci	struct icp_qat_uof_initmem *initmem = obj_handle->init_mem_tab.init_mem;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	for (i = 0; i < obj_handle->init_mem_tab.entry_num; i++) {
4108c2ecf20Sopenharmony_ci		if (initmem->num_in_bytes) {
4118c2ecf20Sopenharmony_ci			if (qat_uclo_init_ae_memory(handle, initmem))
4128c2ecf20Sopenharmony_ci				return -EINVAL;
4138c2ecf20Sopenharmony_ci		}
4148c2ecf20Sopenharmony_ci		initmem = (struct icp_qat_uof_initmem *)((uintptr_t)(
4158c2ecf20Sopenharmony_ci			(uintptr_t)initmem +
4168c2ecf20Sopenharmony_ci			sizeof(struct icp_qat_uof_initmem)) +
4178c2ecf20Sopenharmony_ci			(sizeof(struct icp_qat_uof_memvar_attr) *
4188c2ecf20Sopenharmony_ci			initmem->val_attr_num));
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
4218c2ecf20Sopenharmony_ci		if (qat_hal_batch_wr_lm(handle, ae,
4228c2ecf20Sopenharmony_ci					obj_handle->lm_init_tab[ae])) {
4238c2ecf20Sopenharmony_ci			pr_err("QAT: fail to batch init lmem for AE %d\n", ae);
4248c2ecf20Sopenharmony_ci			return -EINVAL;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci		qat_uclo_cleanup_batch_init_list(handle,
4278c2ecf20Sopenharmony_ci						 &obj_handle->lm_init_tab[ae]);
4288c2ecf20Sopenharmony_ci		qat_uclo_batch_wr_umem(handle, ae,
4298c2ecf20Sopenharmony_ci				       obj_handle->umem_init_tab[ae]);
4308c2ecf20Sopenharmony_ci		qat_uclo_cleanup_batch_init_list(handle,
4318c2ecf20Sopenharmony_ci						 &obj_handle->
4328c2ecf20Sopenharmony_ci						 umem_init_tab[ae]);
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci	return 0;
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic void *qat_uclo_find_chunk(struct icp_qat_uof_objhdr *obj_hdr,
4388c2ecf20Sopenharmony_ci				 char *chunk_id, void *cur)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	int i;
4418c2ecf20Sopenharmony_ci	struct icp_qat_uof_chunkhdr *chunk_hdr =
4428c2ecf20Sopenharmony_ci	    (struct icp_qat_uof_chunkhdr *)
4438c2ecf20Sopenharmony_ci	    ((uintptr_t)obj_hdr + sizeof(struct icp_qat_uof_objhdr));
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	for (i = 0; i < obj_hdr->num_chunks; i++) {
4468c2ecf20Sopenharmony_ci		if ((cur < (void *)&chunk_hdr[i]) &&
4478c2ecf20Sopenharmony_ci		    !strncmp(chunk_hdr[i].chunk_id, chunk_id,
4488c2ecf20Sopenharmony_ci			     ICP_QAT_UOF_OBJID_LEN)) {
4498c2ecf20Sopenharmony_ci			return &chunk_hdr[i];
4508c2ecf20Sopenharmony_ci		}
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci	return NULL;
4538c2ecf20Sopenharmony_ci}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_cistatic unsigned int qat_uclo_calc_checksum(unsigned int reg, int ch)
4568c2ecf20Sopenharmony_ci{
4578c2ecf20Sopenharmony_ci	int i;
4588c2ecf20Sopenharmony_ci	unsigned int topbit = 1 << 0xF;
4598c2ecf20Sopenharmony_ci	unsigned int inbyte = (unsigned int)((reg >> 0x18) ^ ch);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	reg ^= inbyte << 0x8;
4628c2ecf20Sopenharmony_ci	for (i = 0; i < 0x8; i++) {
4638c2ecf20Sopenharmony_ci		if (reg & topbit)
4648c2ecf20Sopenharmony_ci			reg = (reg << 1) ^ 0x1021;
4658c2ecf20Sopenharmony_ci		else
4668c2ecf20Sopenharmony_ci			reg <<= 1;
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci	return reg & 0xFFFF;
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic unsigned int qat_uclo_calc_str_checksum(char *ptr, int num)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	unsigned int chksum = 0;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	if (ptr)
4768c2ecf20Sopenharmony_ci		while (num--)
4778c2ecf20Sopenharmony_ci			chksum = qat_uclo_calc_checksum(chksum, *ptr++);
4788c2ecf20Sopenharmony_ci	return chksum;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic struct icp_qat_uclo_objhdr *
4828c2ecf20Sopenharmony_ciqat_uclo_map_chunk(char *buf, struct icp_qat_uof_filehdr *file_hdr,
4838c2ecf20Sopenharmony_ci		   char *chunk_id)
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	struct icp_qat_uof_filechunkhdr *file_chunk;
4868c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhdr *obj_hdr;
4878c2ecf20Sopenharmony_ci	char *chunk;
4888c2ecf20Sopenharmony_ci	int i;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	file_chunk = (struct icp_qat_uof_filechunkhdr *)
4918c2ecf20Sopenharmony_ci		(buf + sizeof(struct icp_qat_uof_filehdr));
4928c2ecf20Sopenharmony_ci	for (i = 0; i < file_hdr->num_chunks; i++) {
4938c2ecf20Sopenharmony_ci		if (!strncmp(file_chunk->chunk_id, chunk_id,
4948c2ecf20Sopenharmony_ci			     ICP_QAT_UOF_OBJID_LEN)) {
4958c2ecf20Sopenharmony_ci			chunk = buf + file_chunk->offset;
4968c2ecf20Sopenharmony_ci			if (file_chunk->checksum != qat_uclo_calc_str_checksum(
4978c2ecf20Sopenharmony_ci				chunk, file_chunk->size))
4988c2ecf20Sopenharmony_ci				break;
4998c2ecf20Sopenharmony_ci			obj_hdr = kzalloc(sizeof(*obj_hdr), GFP_KERNEL);
5008c2ecf20Sopenharmony_ci			if (!obj_hdr)
5018c2ecf20Sopenharmony_ci				break;
5028c2ecf20Sopenharmony_ci			obj_hdr->file_buff = chunk;
5038c2ecf20Sopenharmony_ci			obj_hdr->checksum = file_chunk->checksum;
5048c2ecf20Sopenharmony_ci			obj_hdr->size = file_chunk->size;
5058c2ecf20Sopenharmony_ci			return obj_hdr;
5068c2ecf20Sopenharmony_ci		}
5078c2ecf20Sopenharmony_ci		file_chunk++;
5088c2ecf20Sopenharmony_ci	}
5098c2ecf20Sopenharmony_ci	return NULL;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic unsigned int
5138c2ecf20Sopenharmony_ciqat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj,
5148c2ecf20Sopenharmony_ci			    struct icp_qat_uof_image *image)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct icp_qat_uof_objtable *uc_var_tab, *imp_var_tab, *imp_expr_tab;
5178c2ecf20Sopenharmony_ci	struct icp_qat_uof_objtable *neigh_reg_tab;
5188c2ecf20Sopenharmony_ci	struct icp_qat_uof_code_page *code_page;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	code_page = (struct icp_qat_uof_code_page *)
5218c2ecf20Sopenharmony_ci			((char *)image + sizeof(struct icp_qat_uof_image));
5228c2ecf20Sopenharmony_ci	uc_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
5238c2ecf20Sopenharmony_ci		     code_page->uc_var_tab_offset);
5248c2ecf20Sopenharmony_ci	imp_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
5258c2ecf20Sopenharmony_ci		      code_page->imp_var_tab_offset);
5268c2ecf20Sopenharmony_ci	imp_expr_tab = (struct icp_qat_uof_objtable *)
5278c2ecf20Sopenharmony_ci		       (encap_uof_obj->beg_uof +
5288c2ecf20Sopenharmony_ci		       code_page->imp_expr_tab_offset);
5298c2ecf20Sopenharmony_ci	if (uc_var_tab->entry_num || imp_var_tab->entry_num ||
5308c2ecf20Sopenharmony_ci	    imp_expr_tab->entry_num) {
5318c2ecf20Sopenharmony_ci		pr_err("QAT: UOF can't contain imported variable to be parsed\n");
5328c2ecf20Sopenharmony_ci		return -EINVAL;
5338c2ecf20Sopenharmony_ci	}
5348c2ecf20Sopenharmony_ci	neigh_reg_tab = (struct icp_qat_uof_objtable *)
5358c2ecf20Sopenharmony_ci			(encap_uof_obj->beg_uof +
5368c2ecf20Sopenharmony_ci			code_page->neigh_reg_tab_offset);
5378c2ecf20Sopenharmony_ci	if (neigh_reg_tab->entry_num) {
5388c2ecf20Sopenharmony_ci		pr_err("QAT: UOF can't contain shared control store feature\n");
5398c2ecf20Sopenharmony_ci		return -EINVAL;
5408c2ecf20Sopenharmony_ci	}
5418c2ecf20Sopenharmony_ci	if (image->numpages > 1) {
5428c2ecf20Sopenharmony_ci		pr_err("QAT: UOF can't contain multiple pages\n");
5438c2ecf20Sopenharmony_ci		return -EINVAL;
5448c2ecf20Sopenharmony_ci	}
5458c2ecf20Sopenharmony_ci	if (ICP_QAT_SHARED_USTORE_MODE(image->ae_mode)) {
5468c2ecf20Sopenharmony_ci		pr_err("QAT: UOF can't use shared control store feature\n");
5478c2ecf20Sopenharmony_ci		return -EFAULT;
5488c2ecf20Sopenharmony_ci	}
5498c2ecf20Sopenharmony_ci	if (RELOADABLE_CTX_SHARED_MODE(image->ae_mode)) {
5508c2ecf20Sopenharmony_ci		pr_err("QAT: UOF can't use reloadable feature\n");
5518c2ecf20Sopenharmony_ci		return -EFAULT;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci	return 0;
5548c2ecf20Sopenharmony_ci}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_cistatic void qat_uclo_map_image_page(struct icp_qat_uof_encap_obj
5578c2ecf20Sopenharmony_ci				     *encap_uof_obj,
5588c2ecf20Sopenharmony_ci				     struct icp_qat_uof_image *img,
5598c2ecf20Sopenharmony_ci				     struct icp_qat_uclo_encap_page *page)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	struct icp_qat_uof_code_page *code_page;
5628c2ecf20Sopenharmony_ci	struct icp_qat_uof_code_area *code_area;
5638c2ecf20Sopenharmony_ci	struct icp_qat_uof_objtable *uword_block_tab;
5648c2ecf20Sopenharmony_ci	struct icp_qat_uof_uword_block *uwblock;
5658c2ecf20Sopenharmony_ci	int i;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	code_page = (struct icp_qat_uof_code_page *)
5688c2ecf20Sopenharmony_ci			((char *)img + sizeof(struct icp_qat_uof_image));
5698c2ecf20Sopenharmony_ci	page->def_page = code_page->def_page;
5708c2ecf20Sopenharmony_ci	page->page_region = code_page->page_region;
5718c2ecf20Sopenharmony_ci	page->beg_addr_v = code_page->beg_addr_v;
5728c2ecf20Sopenharmony_ci	page->beg_addr_p = code_page->beg_addr_p;
5738c2ecf20Sopenharmony_ci	code_area = (struct icp_qat_uof_code_area *)(encap_uof_obj->beg_uof +
5748c2ecf20Sopenharmony_ci						code_page->code_area_offset);
5758c2ecf20Sopenharmony_ci	page->micro_words_num = code_area->micro_words_num;
5768c2ecf20Sopenharmony_ci	uword_block_tab = (struct icp_qat_uof_objtable *)
5778c2ecf20Sopenharmony_ci			  (encap_uof_obj->beg_uof +
5788c2ecf20Sopenharmony_ci			  code_area->uword_block_tab);
5798c2ecf20Sopenharmony_ci	page->uwblock_num = uword_block_tab->entry_num;
5808c2ecf20Sopenharmony_ci	uwblock = (struct icp_qat_uof_uword_block *)((char *)uword_block_tab +
5818c2ecf20Sopenharmony_ci			sizeof(struct icp_qat_uof_objtable));
5828c2ecf20Sopenharmony_ci	page->uwblock = (struct icp_qat_uclo_encap_uwblock *)uwblock;
5838c2ecf20Sopenharmony_ci	for (i = 0; i < uword_block_tab->entry_num; i++)
5848c2ecf20Sopenharmony_ci		page->uwblock[i].micro_words =
5858c2ecf20Sopenharmony_ci		(uintptr_t)encap_uof_obj->beg_uof + uwblock[i].uword_offset;
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_cistatic int qat_uclo_map_uimage(struct icp_qat_uclo_objhandle *obj_handle,
5898c2ecf20Sopenharmony_ci			       struct icp_qat_uclo_encapme *ae_uimage,
5908c2ecf20Sopenharmony_ci			       int max_image)
5918c2ecf20Sopenharmony_ci{
5928c2ecf20Sopenharmony_ci	int i, j;
5938c2ecf20Sopenharmony_ci	struct icp_qat_uof_chunkhdr *chunk_hdr = NULL;
5948c2ecf20Sopenharmony_ci	struct icp_qat_uof_image *image;
5958c2ecf20Sopenharmony_ci	struct icp_qat_uof_objtable *ae_regtab;
5968c2ecf20Sopenharmony_ci	struct icp_qat_uof_objtable *init_reg_sym_tab;
5978c2ecf20Sopenharmony_ci	struct icp_qat_uof_objtable *sbreak_tab;
5988c2ecf20Sopenharmony_ci	struct icp_qat_uof_encap_obj *encap_uof_obj =
5998c2ecf20Sopenharmony_ci					&obj_handle->encap_uof_obj;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	for (j = 0; j < max_image; j++) {
6028c2ecf20Sopenharmony_ci		chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
6038c2ecf20Sopenharmony_ci						ICP_QAT_UOF_IMAG, chunk_hdr);
6048c2ecf20Sopenharmony_ci		if (!chunk_hdr)
6058c2ecf20Sopenharmony_ci			break;
6068c2ecf20Sopenharmony_ci		image = (struct icp_qat_uof_image *)(encap_uof_obj->beg_uof +
6078c2ecf20Sopenharmony_ci						     chunk_hdr->offset);
6088c2ecf20Sopenharmony_ci		ae_regtab = (struct icp_qat_uof_objtable *)
6098c2ecf20Sopenharmony_ci			   (image->reg_tab_offset +
6108c2ecf20Sopenharmony_ci			   obj_handle->obj_hdr->file_buff);
6118c2ecf20Sopenharmony_ci		ae_uimage[j].ae_reg_num = ae_regtab->entry_num;
6128c2ecf20Sopenharmony_ci		ae_uimage[j].ae_reg = (struct icp_qat_uof_ae_reg *)
6138c2ecf20Sopenharmony_ci			(((char *)ae_regtab) +
6148c2ecf20Sopenharmony_ci			sizeof(struct icp_qat_uof_objtable));
6158c2ecf20Sopenharmony_ci		init_reg_sym_tab = (struct icp_qat_uof_objtable *)
6168c2ecf20Sopenharmony_ci				   (image->init_reg_sym_tab +
6178c2ecf20Sopenharmony_ci				   obj_handle->obj_hdr->file_buff);
6188c2ecf20Sopenharmony_ci		ae_uimage[j].init_regsym_num = init_reg_sym_tab->entry_num;
6198c2ecf20Sopenharmony_ci		ae_uimage[j].init_regsym = (struct icp_qat_uof_init_regsym *)
6208c2ecf20Sopenharmony_ci			(((char *)init_reg_sym_tab) +
6218c2ecf20Sopenharmony_ci			sizeof(struct icp_qat_uof_objtable));
6228c2ecf20Sopenharmony_ci		sbreak_tab = (struct icp_qat_uof_objtable *)
6238c2ecf20Sopenharmony_ci			(image->sbreak_tab + obj_handle->obj_hdr->file_buff);
6248c2ecf20Sopenharmony_ci		ae_uimage[j].sbreak_num = sbreak_tab->entry_num;
6258c2ecf20Sopenharmony_ci		ae_uimage[j].sbreak = (struct icp_qat_uof_sbreak *)
6268c2ecf20Sopenharmony_ci				      (((char *)sbreak_tab) +
6278c2ecf20Sopenharmony_ci				      sizeof(struct icp_qat_uof_objtable));
6288c2ecf20Sopenharmony_ci		ae_uimage[j].img_ptr = image;
6298c2ecf20Sopenharmony_ci		if (qat_uclo_check_image_compat(encap_uof_obj, image))
6308c2ecf20Sopenharmony_ci			goto out_err;
6318c2ecf20Sopenharmony_ci		ae_uimage[j].page =
6328c2ecf20Sopenharmony_ci			kzalloc(sizeof(struct icp_qat_uclo_encap_page),
6338c2ecf20Sopenharmony_ci				GFP_KERNEL);
6348c2ecf20Sopenharmony_ci		if (!ae_uimage[j].page)
6358c2ecf20Sopenharmony_ci			goto out_err;
6368c2ecf20Sopenharmony_ci		qat_uclo_map_image_page(encap_uof_obj, image,
6378c2ecf20Sopenharmony_ci					ae_uimage[j].page);
6388c2ecf20Sopenharmony_ci	}
6398c2ecf20Sopenharmony_ci	return j;
6408c2ecf20Sopenharmony_ciout_err:
6418c2ecf20Sopenharmony_ci	for (i = 0; i < j; i++)
6428c2ecf20Sopenharmony_ci		kfree(ae_uimage[i].page);
6438c2ecf20Sopenharmony_ci	return 0;
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic int qat_uclo_map_ae(struct icp_qat_fw_loader_handle *handle, int max_ae)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	int i, ae;
6498c2ecf20Sopenharmony_ci	int mflag = 0;
6508c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	for (ae = 0; ae < max_ae; ae++) {
6538c2ecf20Sopenharmony_ci		if (!test_bit(ae,
6548c2ecf20Sopenharmony_ci			      (unsigned long *)&handle->hal_handle->ae_mask))
6558c2ecf20Sopenharmony_ci			continue;
6568c2ecf20Sopenharmony_ci		for (i = 0; i < obj_handle->uimage_num; i++) {
6578c2ecf20Sopenharmony_ci			if (!test_bit(ae, (unsigned long *)
6588c2ecf20Sopenharmony_ci			&obj_handle->ae_uimage[i].img_ptr->ae_assigned))
6598c2ecf20Sopenharmony_ci				continue;
6608c2ecf20Sopenharmony_ci			mflag = 1;
6618c2ecf20Sopenharmony_ci			if (qat_uclo_init_ae_data(obj_handle, ae, i))
6628c2ecf20Sopenharmony_ci				return -EINVAL;
6638c2ecf20Sopenharmony_ci		}
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci	if (!mflag) {
6668c2ecf20Sopenharmony_ci		pr_err("QAT: uimage uses AE not set\n");
6678c2ecf20Sopenharmony_ci		return -EINVAL;
6688c2ecf20Sopenharmony_ci	}
6698c2ecf20Sopenharmony_ci	return 0;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic struct icp_qat_uof_strtable *
6738c2ecf20Sopenharmony_ciqat_uclo_map_str_table(struct icp_qat_uclo_objhdr *obj_hdr,
6748c2ecf20Sopenharmony_ci		       char *tab_name, struct icp_qat_uof_strtable *str_table)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	struct icp_qat_uof_chunkhdr *chunk_hdr;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	chunk_hdr = qat_uclo_find_chunk((struct icp_qat_uof_objhdr *)
6798c2ecf20Sopenharmony_ci					obj_hdr->file_buff, tab_name, NULL);
6808c2ecf20Sopenharmony_ci	if (chunk_hdr) {
6818c2ecf20Sopenharmony_ci		int hdr_size;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci		memcpy(&str_table->table_len, obj_hdr->file_buff +
6848c2ecf20Sopenharmony_ci		       chunk_hdr->offset, sizeof(str_table->table_len));
6858c2ecf20Sopenharmony_ci		hdr_size = (char *)&str_table->strings - (char *)str_table;
6868c2ecf20Sopenharmony_ci		str_table->strings = (uintptr_t)obj_hdr->file_buff +
6878c2ecf20Sopenharmony_ci					chunk_hdr->offset + hdr_size;
6888c2ecf20Sopenharmony_ci		return str_table;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci	return NULL;
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cistatic void
6948c2ecf20Sopenharmony_ciqat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj *encap_uof_obj,
6958c2ecf20Sopenharmony_ci			   struct icp_qat_uclo_init_mem_table *init_mem_tab)
6968c2ecf20Sopenharmony_ci{
6978c2ecf20Sopenharmony_ci	struct icp_qat_uof_chunkhdr *chunk_hdr;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
7008c2ecf20Sopenharmony_ci					ICP_QAT_UOF_IMEM, NULL);
7018c2ecf20Sopenharmony_ci	if (chunk_hdr) {
7028c2ecf20Sopenharmony_ci		memmove(&init_mem_tab->entry_num, encap_uof_obj->beg_uof +
7038c2ecf20Sopenharmony_ci			chunk_hdr->offset, sizeof(unsigned int));
7048c2ecf20Sopenharmony_ci		init_mem_tab->init_mem = (struct icp_qat_uof_initmem *)
7058c2ecf20Sopenharmony_ci		(encap_uof_obj->beg_uof + chunk_hdr->offset +
7068c2ecf20Sopenharmony_ci		sizeof(unsigned int));
7078c2ecf20Sopenharmony_ci	}
7088c2ecf20Sopenharmony_ci}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_cistatic unsigned int
7118c2ecf20Sopenharmony_ciqat_uclo_get_dev_type(struct icp_qat_fw_loader_handle *handle)
7128c2ecf20Sopenharmony_ci{
7138c2ecf20Sopenharmony_ci	switch (handle->pci_dev->device) {
7148c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_QAT_DH895XCC:
7158c2ecf20Sopenharmony_ci		return ICP_QAT_AC_895XCC_DEV_TYPE;
7168c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_QAT_C62X:
7178c2ecf20Sopenharmony_ci		return ICP_QAT_AC_C62X_DEV_TYPE;
7188c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_QAT_C3XXX:
7198c2ecf20Sopenharmony_ci		return ICP_QAT_AC_C3XXX_DEV_TYPE;
7208c2ecf20Sopenharmony_ci	default:
7218c2ecf20Sopenharmony_ci		pr_err("QAT: unsupported device 0x%x\n",
7228c2ecf20Sopenharmony_ci		       handle->pci_dev->device);
7238c2ecf20Sopenharmony_ci		return 0;
7248c2ecf20Sopenharmony_ci	}
7258c2ecf20Sopenharmony_ci}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_cistatic int qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle *obj_handle)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	unsigned int maj_ver, prod_type = obj_handle->prod_type;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (!(prod_type & obj_handle->encap_uof_obj.obj_hdr->ac_dev_type)) {
7328c2ecf20Sopenharmony_ci		pr_err("QAT: UOF type 0x%x doesn't match with platform 0x%x\n",
7338c2ecf20Sopenharmony_ci		       obj_handle->encap_uof_obj.obj_hdr->ac_dev_type,
7348c2ecf20Sopenharmony_ci		       prod_type);
7358c2ecf20Sopenharmony_ci		return -EINVAL;
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci	maj_ver = obj_handle->prod_rev & 0xff;
7388c2ecf20Sopenharmony_ci	if ((obj_handle->encap_uof_obj.obj_hdr->max_cpu_ver < maj_ver) ||
7398c2ecf20Sopenharmony_ci	    (obj_handle->encap_uof_obj.obj_hdr->min_cpu_ver > maj_ver)) {
7408c2ecf20Sopenharmony_ci		pr_err("QAT: UOF majVer 0x%x out of range\n", maj_ver);
7418c2ecf20Sopenharmony_ci		return -EINVAL;
7428c2ecf20Sopenharmony_ci	}
7438c2ecf20Sopenharmony_ci	return 0;
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle,
7478c2ecf20Sopenharmony_ci			     unsigned char ae, unsigned char ctx_mask,
7488c2ecf20Sopenharmony_ci			     enum icp_qat_uof_regtype reg_type,
7498c2ecf20Sopenharmony_ci			     unsigned short reg_addr, unsigned int value)
7508c2ecf20Sopenharmony_ci{
7518c2ecf20Sopenharmony_ci	switch (reg_type) {
7528c2ecf20Sopenharmony_ci	case ICP_GPA_ABS:
7538c2ecf20Sopenharmony_ci	case ICP_GPB_ABS:
7548c2ecf20Sopenharmony_ci		ctx_mask = 0;
7558c2ecf20Sopenharmony_ci		fallthrough;
7568c2ecf20Sopenharmony_ci	case ICP_GPA_REL:
7578c2ecf20Sopenharmony_ci	case ICP_GPB_REL:
7588c2ecf20Sopenharmony_ci		return qat_hal_init_gpr(handle, ae, ctx_mask, reg_type,
7598c2ecf20Sopenharmony_ci					reg_addr, value);
7608c2ecf20Sopenharmony_ci	case ICP_SR_ABS:
7618c2ecf20Sopenharmony_ci	case ICP_DR_ABS:
7628c2ecf20Sopenharmony_ci	case ICP_SR_RD_ABS:
7638c2ecf20Sopenharmony_ci	case ICP_DR_RD_ABS:
7648c2ecf20Sopenharmony_ci		ctx_mask = 0;
7658c2ecf20Sopenharmony_ci		fallthrough;
7668c2ecf20Sopenharmony_ci	case ICP_SR_REL:
7678c2ecf20Sopenharmony_ci	case ICP_DR_REL:
7688c2ecf20Sopenharmony_ci	case ICP_SR_RD_REL:
7698c2ecf20Sopenharmony_ci	case ICP_DR_RD_REL:
7708c2ecf20Sopenharmony_ci		return qat_hal_init_rd_xfer(handle, ae, ctx_mask, reg_type,
7718c2ecf20Sopenharmony_ci					    reg_addr, value);
7728c2ecf20Sopenharmony_ci	case ICP_SR_WR_ABS:
7738c2ecf20Sopenharmony_ci	case ICP_DR_WR_ABS:
7748c2ecf20Sopenharmony_ci		ctx_mask = 0;
7758c2ecf20Sopenharmony_ci		fallthrough;
7768c2ecf20Sopenharmony_ci	case ICP_SR_WR_REL:
7778c2ecf20Sopenharmony_ci	case ICP_DR_WR_REL:
7788c2ecf20Sopenharmony_ci		return qat_hal_init_wr_xfer(handle, ae, ctx_mask, reg_type,
7798c2ecf20Sopenharmony_ci					    reg_addr, value);
7808c2ecf20Sopenharmony_ci	case ICP_NEIGH_REL:
7818c2ecf20Sopenharmony_ci		return qat_hal_init_nn(handle, ae, ctx_mask, reg_addr, value);
7828c2ecf20Sopenharmony_ci	default:
7838c2ecf20Sopenharmony_ci		pr_err("QAT: UOF uses not supported reg type 0x%x\n", reg_type);
7848c2ecf20Sopenharmony_ci		return -EFAULT;
7858c2ecf20Sopenharmony_ci	}
7868c2ecf20Sopenharmony_ci	return 0;
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_cistatic int qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle *handle,
7908c2ecf20Sopenharmony_ci				 unsigned int ae,
7918c2ecf20Sopenharmony_ci				 struct icp_qat_uclo_encapme *encap_ae)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	unsigned int i;
7948c2ecf20Sopenharmony_ci	unsigned char ctx_mask;
7958c2ecf20Sopenharmony_ci	struct icp_qat_uof_init_regsym *init_regsym;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	if (ICP_QAT_CTX_MODE(encap_ae->img_ptr->ae_mode) ==
7988c2ecf20Sopenharmony_ci	    ICP_QAT_UCLO_MAX_CTX)
7998c2ecf20Sopenharmony_ci		ctx_mask = 0xff;
8008c2ecf20Sopenharmony_ci	else
8018c2ecf20Sopenharmony_ci		ctx_mask = 0x55;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	for (i = 0; i < encap_ae->init_regsym_num; i++) {
8048c2ecf20Sopenharmony_ci		unsigned int exp_res;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci		init_regsym = &encap_ae->init_regsym[i];
8078c2ecf20Sopenharmony_ci		exp_res = init_regsym->value;
8088c2ecf20Sopenharmony_ci		switch (init_regsym->init_type) {
8098c2ecf20Sopenharmony_ci		case ICP_QAT_UOF_INIT_REG:
8108c2ecf20Sopenharmony_ci			qat_uclo_init_reg(handle, ae, ctx_mask,
8118c2ecf20Sopenharmony_ci					  (enum icp_qat_uof_regtype)
8128c2ecf20Sopenharmony_ci					  init_regsym->reg_type,
8138c2ecf20Sopenharmony_ci					  (unsigned short)init_regsym->reg_addr,
8148c2ecf20Sopenharmony_ci					  exp_res);
8158c2ecf20Sopenharmony_ci			break;
8168c2ecf20Sopenharmony_ci		case ICP_QAT_UOF_INIT_REG_CTX:
8178c2ecf20Sopenharmony_ci			/* check if ctx is appropriate for the ctxMode */
8188c2ecf20Sopenharmony_ci			if (!((1 << init_regsym->ctx) & ctx_mask)) {
8198c2ecf20Sopenharmony_ci				pr_err("QAT: invalid ctx num = 0x%x\n",
8208c2ecf20Sopenharmony_ci				       init_regsym->ctx);
8218c2ecf20Sopenharmony_ci				return -EINVAL;
8228c2ecf20Sopenharmony_ci			}
8238c2ecf20Sopenharmony_ci			qat_uclo_init_reg(handle, ae,
8248c2ecf20Sopenharmony_ci					  (unsigned char)
8258c2ecf20Sopenharmony_ci					  (1 << init_regsym->ctx),
8268c2ecf20Sopenharmony_ci					  (enum icp_qat_uof_regtype)
8278c2ecf20Sopenharmony_ci					  init_regsym->reg_type,
8288c2ecf20Sopenharmony_ci					  (unsigned short)init_regsym->reg_addr,
8298c2ecf20Sopenharmony_ci					  exp_res);
8308c2ecf20Sopenharmony_ci			break;
8318c2ecf20Sopenharmony_ci		case ICP_QAT_UOF_INIT_EXPR:
8328c2ecf20Sopenharmony_ci			pr_err("QAT: INIT_EXPR feature not supported\n");
8338c2ecf20Sopenharmony_ci			return -EINVAL;
8348c2ecf20Sopenharmony_ci		case ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP:
8358c2ecf20Sopenharmony_ci			pr_err("QAT: INIT_EXPR_ENDIAN_SWAP feature not supported\n");
8368c2ecf20Sopenharmony_ci			return -EINVAL;
8378c2ecf20Sopenharmony_ci		default:
8388c2ecf20Sopenharmony_ci			break;
8398c2ecf20Sopenharmony_ci		}
8408c2ecf20Sopenharmony_ci	}
8418c2ecf20Sopenharmony_ci	return 0;
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic int qat_uclo_init_globals(struct icp_qat_fw_loader_handle *handle)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
8478c2ecf20Sopenharmony_ci	unsigned int s, ae;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (obj_handle->global_inited)
8508c2ecf20Sopenharmony_ci		return 0;
8518c2ecf20Sopenharmony_ci	if (obj_handle->init_mem_tab.entry_num) {
8528c2ecf20Sopenharmony_ci		if (qat_uclo_init_memory(handle)) {
8538c2ecf20Sopenharmony_ci			pr_err("QAT: initialize memory failed\n");
8548c2ecf20Sopenharmony_ci			return -EINVAL;
8558c2ecf20Sopenharmony_ci		}
8568c2ecf20Sopenharmony_ci	}
8578c2ecf20Sopenharmony_ci	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
8588c2ecf20Sopenharmony_ci		for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
8598c2ecf20Sopenharmony_ci			if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
8608c2ecf20Sopenharmony_ci				continue;
8618c2ecf20Sopenharmony_ci			if (qat_uclo_init_reg_sym(handle, ae,
8628c2ecf20Sopenharmony_ci						  obj_handle->ae_data[ae].
8638c2ecf20Sopenharmony_ci						  ae_slices[s].encap_image))
8648c2ecf20Sopenharmony_ci				return -EINVAL;
8658c2ecf20Sopenharmony_ci		}
8668c2ecf20Sopenharmony_ci	}
8678c2ecf20Sopenharmony_ci	obj_handle->global_inited = 1;
8688c2ecf20Sopenharmony_ci	return 0;
8698c2ecf20Sopenharmony_ci}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_cistatic int qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle *handle)
8728c2ecf20Sopenharmony_ci{
8738c2ecf20Sopenharmony_ci	unsigned char ae, nn_mode, s;
8748c2ecf20Sopenharmony_ci	struct icp_qat_uof_image *uof_image;
8758c2ecf20Sopenharmony_ci	struct icp_qat_uclo_aedata *ae_data;
8768c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
8798c2ecf20Sopenharmony_ci		if (!test_bit(ae,
8808c2ecf20Sopenharmony_ci			      (unsigned long *)&handle->hal_handle->ae_mask))
8818c2ecf20Sopenharmony_ci			continue;
8828c2ecf20Sopenharmony_ci		ae_data = &obj_handle->ae_data[ae];
8838c2ecf20Sopenharmony_ci		for (s = 0; s < min_t(unsigned int, ae_data->slice_num,
8848c2ecf20Sopenharmony_ci				      ICP_QAT_UCLO_MAX_CTX); s++) {
8858c2ecf20Sopenharmony_ci			if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
8868c2ecf20Sopenharmony_ci				continue;
8878c2ecf20Sopenharmony_ci			uof_image = ae_data->ae_slices[s].encap_image->img_ptr;
8888c2ecf20Sopenharmony_ci			if (qat_hal_set_ae_ctx_mode(handle, ae,
8898c2ecf20Sopenharmony_ci						    (char)ICP_QAT_CTX_MODE
8908c2ecf20Sopenharmony_ci						    (uof_image->ae_mode))) {
8918c2ecf20Sopenharmony_ci				pr_err("QAT: qat_hal_set_ae_ctx_mode error\n");
8928c2ecf20Sopenharmony_ci				return -EFAULT;
8938c2ecf20Sopenharmony_ci			}
8948c2ecf20Sopenharmony_ci			nn_mode = ICP_QAT_NN_MODE(uof_image->ae_mode);
8958c2ecf20Sopenharmony_ci			if (qat_hal_set_ae_nn_mode(handle, ae, nn_mode)) {
8968c2ecf20Sopenharmony_ci				pr_err("QAT: qat_hal_set_ae_nn_mode error\n");
8978c2ecf20Sopenharmony_ci				return -EFAULT;
8988c2ecf20Sopenharmony_ci			}
8998c2ecf20Sopenharmony_ci			if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM0,
9008c2ecf20Sopenharmony_ci						   (char)ICP_QAT_LOC_MEM0_MODE
9018c2ecf20Sopenharmony_ci						   (uof_image->ae_mode))) {
9028c2ecf20Sopenharmony_ci				pr_err("QAT: qat_hal_set_ae_lm_mode LMEM0 error\n");
9038c2ecf20Sopenharmony_ci				return -EFAULT;
9048c2ecf20Sopenharmony_ci			}
9058c2ecf20Sopenharmony_ci			if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM1,
9068c2ecf20Sopenharmony_ci						   (char)ICP_QAT_LOC_MEM1_MODE
9078c2ecf20Sopenharmony_ci						   (uof_image->ae_mode))) {
9088c2ecf20Sopenharmony_ci				pr_err("QAT: qat_hal_set_ae_lm_mode LMEM1 error\n");
9098c2ecf20Sopenharmony_ci				return -EFAULT;
9108c2ecf20Sopenharmony_ci			}
9118c2ecf20Sopenharmony_ci		}
9128c2ecf20Sopenharmony_ci	}
9138c2ecf20Sopenharmony_ci	return 0;
9148c2ecf20Sopenharmony_ci}
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_cistatic void qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle *handle)
9178c2ecf20Sopenharmony_ci{
9188c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
9198c2ecf20Sopenharmony_ci	struct icp_qat_uclo_encapme *image;
9208c2ecf20Sopenharmony_ci	int a;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	for (a = 0; a < obj_handle->uimage_num; a++) {
9238c2ecf20Sopenharmony_ci		image = &obj_handle->ae_uimage[a];
9248c2ecf20Sopenharmony_ci		image->uwords_num = image->page->beg_addr_p +
9258c2ecf20Sopenharmony_ci					image->page->micro_words_num;
9268c2ecf20Sopenharmony_ci	}
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistatic int qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle *handle)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
9328c2ecf20Sopenharmony_ci	unsigned int ae;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	obj_handle->encap_uof_obj.beg_uof = obj_handle->obj_hdr->file_buff;
9358c2ecf20Sopenharmony_ci	obj_handle->encap_uof_obj.obj_hdr = (struct icp_qat_uof_objhdr *)
9368c2ecf20Sopenharmony_ci					     obj_handle->obj_hdr->file_buff;
9378c2ecf20Sopenharmony_ci	obj_handle->uword_in_bytes = 6;
9388c2ecf20Sopenharmony_ci	obj_handle->prod_type = qat_uclo_get_dev_type(handle);
9398c2ecf20Sopenharmony_ci	obj_handle->prod_rev = PID_MAJOR_REV |
9408c2ecf20Sopenharmony_ci			(PID_MINOR_REV & handle->hal_handle->revision_id);
9418c2ecf20Sopenharmony_ci	if (qat_uclo_check_uof_compat(obj_handle)) {
9428c2ecf20Sopenharmony_ci		pr_err("QAT: UOF incompatible\n");
9438c2ecf20Sopenharmony_ci		return -EINVAL;
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci	obj_handle->uword_buf = kcalloc(UWORD_CPYBUF_SIZE, sizeof(u64),
9468c2ecf20Sopenharmony_ci					GFP_KERNEL);
9478c2ecf20Sopenharmony_ci	if (!obj_handle->uword_buf)
9488c2ecf20Sopenharmony_ci		return -ENOMEM;
9498c2ecf20Sopenharmony_ci	obj_handle->ustore_phy_size = ICP_QAT_UCLO_MAX_USTORE;
9508c2ecf20Sopenharmony_ci	if (!obj_handle->obj_hdr->file_buff ||
9518c2ecf20Sopenharmony_ci	    !qat_uclo_map_str_table(obj_handle->obj_hdr, ICP_QAT_UOF_STRT,
9528c2ecf20Sopenharmony_ci				    &obj_handle->str_table)) {
9538c2ecf20Sopenharmony_ci		pr_err("QAT: UOF doesn't have effective images\n");
9548c2ecf20Sopenharmony_ci		goto out_err;
9558c2ecf20Sopenharmony_ci	}
9568c2ecf20Sopenharmony_ci	obj_handle->uimage_num =
9578c2ecf20Sopenharmony_ci		qat_uclo_map_uimage(obj_handle, obj_handle->ae_uimage,
9588c2ecf20Sopenharmony_ci				    ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX);
9598c2ecf20Sopenharmony_ci	if (!obj_handle->uimage_num)
9608c2ecf20Sopenharmony_ci		goto out_err;
9618c2ecf20Sopenharmony_ci	if (qat_uclo_map_ae(handle, handle->hal_handle->ae_max_num)) {
9628c2ecf20Sopenharmony_ci		pr_err("QAT: Bad object\n");
9638c2ecf20Sopenharmony_ci		goto out_check_uof_aemask_err;
9648c2ecf20Sopenharmony_ci	}
9658c2ecf20Sopenharmony_ci	qat_uclo_init_uword_num(handle);
9668c2ecf20Sopenharmony_ci	qat_uclo_map_initmem_table(&obj_handle->encap_uof_obj,
9678c2ecf20Sopenharmony_ci				   &obj_handle->init_mem_tab);
9688c2ecf20Sopenharmony_ci	if (qat_uclo_set_ae_mode(handle))
9698c2ecf20Sopenharmony_ci		goto out_check_uof_aemask_err;
9708c2ecf20Sopenharmony_ci	return 0;
9718c2ecf20Sopenharmony_ciout_check_uof_aemask_err:
9728c2ecf20Sopenharmony_ci	for (ae = 0; ae < obj_handle->uimage_num; ae++)
9738c2ecf20Sopenharmony_ci		kfree(obj_handle->ae_uimage[ae].page);
9748c2ecf20Sopenharmony_ciout_err:
9758c2ecf20Sopenharmony_ci	kfree(obj_handle->uword_buf);
9768c2ecf20Sopenharmony_ci	return -EFAULT;
9778c2ecf20Sopenharmony_ci}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_cistatic int qat_uclo_map_suof_file_hdr(struct icp_qat_fw_loader_handle *handle,
9808c2ecf20Sopenharmony_ci				      struct icp_qat_suof_filehdr *suof_ptr,
9818c2ecf20Sopenharmony_ci				      int suof_size)
9828c2ecf20Sopenharmony_ci{
9838c2ecf20Sopenharmony_ci	unsigned int check_sum = 0;
9848c2ecf20Sopenharmony_ci	unsigned int min_ver_offset = 0;
9858c2ecf20Sopenharmony_ci	struct icp_qat_suof_handle *suof_handle = handle->sobj_handle;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	suof_handle->file_id = ICP_QAT_SUOF_FID;
9888c2ecf20Sopenharmony_ci	suof_handle->suof_buf = (char *)suof_ptr;
9898c2ecf20Sopenharmony_ci	suof_handle->suof_size = suof_size;
9908c2ecf20Sopenharmony_ci	min_ver_offset = suof_size - offsetof(struct icp_qat_suof_filehdr,
9918c2ecf20Sopenharmony_ci					      min_ver);
9928c2ecf20Sopenharmony_ci	check_sum = qat_uclo_calc_str_checksum((char *)&suof_ptr->min_ver,
9938c2ecf20Sopenharmony_ci					       min_ver_offset);
9948c2ecf20Sopenharmony_ci	if (check_sum != suof_ptr->check_sum) {
9958c2ecf20Sopenharmony_ci		pr_err("QAT: incorrect SUOF checksum\n");
9968c2ecf20Sopenharmony_ci		return -EINVAL;
9978c2ecf20Sopenharmony_ci	}
9988c2ecf20Sopenharmony_ci	suof_handle->check_sum = suof_ptr->check_sum;
9998c2ecf20Sopenharmony_ci	suof_handle->min_ver = suof_ptr->min_ver;
10008c2ecf20Sopenharmony_ci	suof_handle->maj_ver = suof_ptr->maj_ver;
10018c2ecf20Sopenharmony_ci	suof_handle->fw_type = suof_ptr->fw_type;
10028c2ecf20Sopenharmony_ci	return 0;
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_cistatic void qat_uclo_map_simg(struct icp_qat_suof_handle *suof_handle,
10068c2ecf20Sopenharmony_ci			      struct icp_qat_suof_img_hdr *suof_img_hdr,
10078c2ecf20Sopenharmony_ci			      struct icp_qat_suof_chunk_hdr *suof_chunk_hdr)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	struct icp_qat_simg_ae_mode *ae_mode;
10108c2ecf20Sopenharmony_ci	struct icp_qat_suof_objhdr *suof_objhdr;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	suof_img_hdr->simg_buf  = (suof_handle->suof_buf +
10138c2ecf20Sopenharmony_ci				   suof_chunk_hdr->offset +
10148c2ecf20Sopenharmony_ci				   sizeof(*suof_objhdr));
10158c2ecf20Sopenharmony_ci	suof_img_hdr->simg_len = ((struct icp_qat_suof_objhdr *)(uintptr_t)
10168c2ecf20Sopenharmony_ci				  (suof_handle->suof_buf +
10178c2ecf20Sopenharmony_ci				   suof_chunk_hdr->offset))->img_length;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	suof_img_hdr->css_header = suof_img_hdr->simg_buf;
10208c2ecf20Sopenharmony_ci	suof_img_hdr->css_key = (suof_img_hdr->css_header +
10218c2ecf20Sopenharmony_ci				 sizeof(struct icp_qat_css_hdr));
10228c2ecf20Sopenharmony_ci	suof_img_hdr->css_signature = suof_img_hdr->css_key +
10238c2ecf20Sopenharmony_ci				      ICP_QAT_CSS_FWSK_MODULUS_LEN +
10248c2ecf20Sopenharmony_ci				      ICP_QAT_CSS_FWSK_EXPONENT_LEN;
10258c2ecf20Sopenharmony_ci	suof_img_hdr->css_simg = suof_img_hdr->css_signature +
10268c2ecf20Sopenharmony_ci				 ICP_QAT_CSS_SIGNATURE_LEN;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	ae_mode = (struct icp_qat_simg_ae_mode *)(suof_img_hdr->css_simg);
10298c2ecf20Sopenharmony_ci	suof_img_hdr->ae_mask = ae_mode->ae_mask;
10308c2ecf20Sopenharmony_ci	suof_img_hdr->simg_name = (unsigned long)&ae_mode->simg_name;
10318c2ecf20Sopenharmony_ci	suof_img_hdr->appmeta_data = (unsigned long)&ae_mode->appmeta_data;
10328c2ecf20Sopenharmony_ci	suof_img_hdr->fw_type = ae_mode->fw_type;
10338c2ecf20Sopenharmony_ci}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_cistatic void
10368c2ecf20Sopenharmony_ciqat_uclo_map_suof_symobjs(struct icp_qat_suof_handle *suof_handle,
10378c2ecf20Sopenharmony_ci			  struct icp_qat_suof_chunk_hdr *suof_chunk_hdr)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	char **sym_str = (char **)&suof_handle->sym_str;
10408c2ecf20Sopenharmony_ci	unsigned int *sym_size = &suof_handle->sym_size;
10418c2ecf20Sopenharmony_ci	struct icp_qat_suof_strtable *str_table_obj;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	*sym_size = *(unsigned int *)(uintptr_t)
10448c2ecf20Sopenharmony_ci		   (suof_chunk_hdr->offset + suof_handle->suof_buf);
10458c2ecf20Sopenharmony_ci	*sym_str = (char *)(uintptr_t)
10468c2ecf20Sopenharmony_ci		   (suof_handle->suof_buf + suof_chunk_hdr->offset +
10478c2ecf20Sopenharmony_ci		   sizeof(str_table_obj->tab_length));
10488c2ecf20Sopenharmony_ci}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_cistatic int qat_uclo_check_simg_compat(struct icp_qat_fw_loader_handle *handle,
10518c2ecf20Sopenharmony_ci				      struct icp_qat_suof_img_hdr *img_hdr)
10528c2ecf20Sopenharmony_ci{
10538c2ecf20Sopenharmony_ci	struct icp_qat_simg_ae_mode *img_ae_mode = NULL;
10548c2ecf20Sopenharmony_ci	unsigned int prod_rev, maj_ver, prod_type;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	prod_type = qat_uclo_get_dev_type(handle);
10578c2ecf20Sopenharmony_ci	img_ae_mode = (struct icp_qat_simg_ae_mode *)img_hdr->css_simg;
10588c2ecf20Sopenharmony_ci	prod_rev = PID_MAJOR_REV |
10598c2ecf20Sopenharmony_ci			 (PID_MINOR_REV & handle->hal_handle->revision_id);
10608c2ecf20Sopenharmony_ci	if (img_ae_mode->dev_type != prod_type) {
10618c2ecf20Sopenharmony_ci		pr_err("QAT: incompatible product type %x\n",
10628c2ecf20Sopenharmony_ci		       img_ae_mode->dev_type);
10638c2ecf20Sopenharmony_ci		return -EINVAL;
10648c2ecf20Sopenharmony_ci	}
10658c2ecf20Sopenharmony_ci	maj_ver = prod_rev & 0xff;
10668c2ecf20Sopenharmony_ci	if ((maj_ver > img_ae_mode->devmax_ver) ||
10678c2ecf20Sopenharmony_ci	    (maj_ver < img_ae_mode->devmin_ver)) {
10688c2ecf20Sopenharmony_ci		pr_err("QAT: incompatible device majver 0x%x\n", maj_ver);
10698c2ecf20Sopenharmony_ci		return -EINVAL;
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci	return 0;
10728c2ecf20Sopenharmony_ci}
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_cistatic void qat_uclo_del_suof(struct icp_qat_fw_loader_handle *handle)
10758c2ecf20Sopenharmony_ci{
10768c2ecf20Sopenharmony_ci	struct icp_qat_suof_handle *sobj_handle = handle->sobj_handle;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	kfree(sobj_handle->img_table.simg_hdr);
10798c2ecf20Sopenharmony_ci	sobj_handle->img_table.simg_hdr = NULL;
10808c2ecf20Sopenharmony_ci	kfree(handle->sobj_handle);
10818c2ecf20Sopenharmony_ci	handle->sobj_handle = NULL;
10828c2ecf20Sopenharmony_ci}
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_cistatic void qat_uclo_tail_img(struct icp_qat_suof_img_hdr *suof_img_hdr,
10858c2ecf20Sopenharmony_ci			      unsigned int img_id, unsigned int num_simgs)
10868c2ecf20Sopenharmony_ci{
10878c2ecf20Sopenharmony_ci	struct icp_qat_suof_img_hdr img_header;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	if (img_id != num_simgs - 1) {
10908c2ecf20Sopenharmony_ci		memcpy(&img_header, &suof_img_hdr[num_simgs - 1],
10918c2ecf20Sopenharmony_ci		       sizeof(*suof_img_hdr));
10928c2ecf20Sopenharmony_ci		memcpy(&suof_img_hdr[num_simgs - 1], &suof_img_hdr[img_id],
10938c2ecf20Sopenharmony_ci		       sizeof(*suof_img_hdr));
10948c2ecf20Sopenharmony_ci		memcpy(&suof_img_hdr[img_id], &img_header,
10958c2ecf20Sopenharmony_ci		       sizeof(*suof_img_hdr));
10968c2ecf20Sopenharmony_ci	}
10978c2ecf20Sopenharmony_ci}
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_cistatic int qat_uclo_map_suof(struct icp_qat_fw_loader_handle *handle,
11008c2ecf20Sopenharmony_ci			     struct icp_qat_suof_filehdr *suof_ptr,
11018c2ecf20Sopenharmony_ci			     int suof_size)
11028c2ecf20Sopenharmony_ci{
11038c2ecf20Sopenharmony_ci	struct icp_qat_suof_handle *suof_handle = handle->sobj_handle;
11048c2ecf20Sopenharmony_ci	struct icp_qat_suof_chunk_hdr *suof_chunk_hdr = NULL;
11058c2ecf20Sopenharmony_ci	struct icp_qat_suof_img_hdr *suof_img_hdr = NULL;
11068c2ecf20Sopenharmony_ci	int ret = 0, ae0_img = ICP_QAT_UCLO_MAX_AE;
11078c2ecf20Sopenharmony_ci	unsigned int i = 0;
11088c2ecf20Sopenharmony_ci	struct icp_qat_suof_img_hdr img_header;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	if (!suof_ptr || (suof_size == 0)) {
11118c2ecf20Sopenharmony_ci		pr_err("QAT: input parameter SUOF pointer/size is NULL\n");
11128c2ecf20Sopenharmony_ci		return -EINVAL;
11138c2ecf20Sopenharmony_ci	}
11148c2ecf20Sopenharmony_ci	if (qat_uclo_check_suof_format(suof_ptr))
11158c2ecf20Sopenharmony_ci		return -EINVAL;
11168c2ecf20Sopenharmony_ci	ret = qat_uclo_map_suof_file_hdr(handle, suof_ptr, suof_size);
11178c2ecf20Sopenharmony_ci	if (ret)
11188c2ecf20Sopenharmony_ci		return ret;
11198c2ecf20Sopenharmony_ci	suof_chunk_hdr = (struct icp_qat_suof_chunk_hdr *)
11208c2ecf20Sopenharmony_ci			 ((uintptr_t)suof_ptr + sizeof(*suof_ptr));
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	qat_uclo_map_suof_symobjs(suof_handle, suof_chunk_hdr);
11238c2ecf20Sopenharmony_ci	suof_handle->img_table.num_simgs = suof_ptr->num_chunks - 1;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	if (suof_handle->img_table.num_simgs != 0) {
11268c2ecf20Sopenharmony_ci		suof_img_hdr = kcalloc(suof_handle->img_table.num_simgs,
11278c2ecf20Sopenharmony_ci				       sizeof(img_header),
11288c2ecf20Sopenharmony_ci				       GFP_KERNEL);
11298c2ecf20Sopenharmony_ci		if (!suof_img_hdr)
11308c2ecf20Sopenharmony_ci			return -ENOMEM;
11318c2ecf20Sopenharmony_ci		suof_handle->img_table.simg_hdr = suof_img_hdr;
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	for (i = 0; i < suof_handle->img_table.num_simgs; i++) {
11358c2ecf20Sopenharmony_ci		qat_uclo_map_simg(handle->sobj_handle, &suof_img_hdr[i],
11368c2ecf20Sopenharmony_ci				  &suof_chunk_hdr[1 + i]);
11378c2ecf20Sopenharmony_ci		ret = qat_uclo_check_simg_compat(handle,
11388c2ecf20Sopenharmony_ci						 &suof_img_hdr[i]);
11398c2ecf20Sopenharmony_ci		if (ret)
11408c2ecf20Sopenharmony_ci			return ret;
11418c2ecf20Sopenharmony_ci		if ((suof_img_hdr[i].ae_mask & 0x1) != 0)
11428c2ecf20Sopenharmony_ci			ae0_img = i;
11438c2ecf20Sopenharmony_ci	}
11448c2ecf20Sopenharmony_ci	qat_uclo_tail_img(suof_img_hdr, ae0_img,
11458c2ecf20Sopenharmony_ci			  suof_handle->img_table.num_simgs);
11468c2ecf20Sopenharmony_ci	return 0;
11478c2ecf20Sopenharmony_ci}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci#define ADD_ADDR(high, low)  ((((u64)high) << 32) + low)
11508c2ecf20Sopenharmony_ci#define BITS_IN_DWORD 32
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_cistatic int qat_uclo_auth_fw(struct icp_qat_fw_loader_handle *handle,
11538c2ecf20Sopenharmony_ci			    struct icp_qat_fw_auth_desc *desc)
11548c2ecf20Sopenharmony_ci{
11558c2ecf20Sopenharmony_ci	unsigned int fcu_sts, retry = 0;
11568c2ecf20Sopenharmony_ci	u64 bus_addr;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	bus_addr = ADD_ADDR(desc->css_hdr_high, desc->css_hdr_low)
11598c2ecf20Sopenharmony_ci			   - sizeof(struct icp_qat_auth_chunk);
11608c2ecf20Sopenharmony_ci	SET_CAP_CSR(handle, FCU_DRAM_ADDR_HI, (bus_addr >> BITS_IN_DWORD));
11618c2ecf20Sopenharmony_ci	SET_CAP_CSR(handle, FCU_DRAM_ADDR_LO, bus_addr);
11628c2ecf20Sopenharmony_ci	SET_CAP_CSR(handle, FCU_CONTROL, FCU_CTRL_CMD_AUTH);
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	do {
11658c2ecf20Sopenharmony_ci		msleep(FW_AUTH_WAIT_PERIOD);
11668c2ecf20Sopenharmony_ci		fcu_sts = GET_CAP_CSR(handle, FCU_STATUS);
11678c2ecf20Sopenharmony_ci		if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_FAIL)
11688c2ecf20Sopenharmony_ci			goto auth_fail;
11698c2ecf20Sopenharmony_ci		if (((fcu_sts >> FCU_STS_AUTHFWLD_POS) & 0x1))
11708c2ecf20Sopenharmony_ci			if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_DONE)
11718c2ecf20Sopenharmony_ci				return 0;
11728c2ecf20Sopenharmony_ci	} while (retry++ < FW_AUTH_MAX_RETRY);
11738c2ecf20Sopenharmony_ciauth_fail:
11748c2ecf20Sopenharmony_ci	pr_err("QAT: authentication error (FCU_STATUS = 0x%x),retry = %d\n",
11758c2ecf20Sopenharmony_ci	       fcu_sts & FCU_AUTH_STS_MASK, retry);
11768c2ecf20Sopenharmony_ci	return -EINVAL;
11778c2ecf20Sopenharmony_ci}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_cistatic int qat_uclo_simg_alloc(struct icp_qat_fw_loader_handle *handle,
11808c2ecf20Sopenharmony_ci			       struct icp_firml_dram_desc *dram_desc,
11818c2ecf20Sopenharmony_ci			       unsigned int size)
11828c2ecf20Sopenharmony_ci{
11838c2ecf20Sopenharmony_ci	void *vptr;
11848c2ecf20Sopenharmony_ci	dma_addr_t ptr;
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	vptr = dma_alloc_coherent(&handle->pci_dev->dev,
11878c2ecf20Sopenharmony_ci				  size, &ptr, GFP_KERNEL);
11888c2ecf20Sopenharmony_ci	if (!vptr)
11898c2ecf20Sopenharmony_ci		return -ENOMEM;
11908c2ecf20Sopenharmony_ci	dram_desc->dram_base_addr_v = vptr;
11918c2ecf20Sopenharmony_ci	dram_desc->dram_bus_addr = ptr;
11928c2ecf20Sopenharmony_ci	dram_desc->dram_size = size;
11938c2ecf20Sopenharmony_ci	return 0;
11948c2ecf20Sopenharmony_ci}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_cistatic void qat_uclo_simg_free(struct icp_qat_fw_loader_handle *handle,
11978c2ecf20Sopenharmony_ci			       struct icp_firml_dram_desc *dram_desc)
11988c2ecf20Sopenharmony_ci{
11998c2ecf20Sopenharmony_ci	dma_free_coherent(&handle->pci_dev->dev,
12008c2ecf20Sopenharmony_ci			  (size_t)(dram_desc->dram_size),
12018c2ecf20Sopenharmony_ci			  (dram_desc->dram_base_addr_v),
12028c2ecf20Sopenharmony_ci			  dram_desc->dram_bus_addr);
12038c2ecf20Sopenharmony_ci	memset(dram_desc, 0, sizeof(*dram_desc));
12048c2ecf20Sopenharmony_ci}
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_cistatic void qat_uclo_ummap_auth_fw(struct icp_qat_fw_loader_handle *handle,
12078c2ecf20Sopenharmony_ci				   struct icp_qat_fw_auth_desc **desc)
12088c2ecf20Sopenharmony_ci{
12098c2ecf20Sopenharmony_ci	struct icp_firml_dram_desc dram_desc;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	dram_desc.dram_base_addr_v = *desc;
12128c2ecf20Sopenharmony_ci	dram_desc.dram_bus_addr = ((struct icp_qat_auth_chunk *)
12138c2ecf20Sopenharmony_ci				   (*desc))->chunk_bus_addr;
12148c2ecf20Sopenharmony_ci	dram_desc.dram_size = ((struct icp_qat_auth_chunk *)
12158c2ecf20Sopenharmony_ci			       (*desc))->chunk_size;
12168c2ecf20Sopenharmony_ci	qat_uclo_simg_free(handle, &dram_desc);
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_cistatic int qat_uclo_map_auth_fw(struct icp_qat_fw_loader_handle *handle,
12208c2ecf20Sopenharmony_ci				char *image, unsigned int size,
12218c2ecf20Sopenharmony_ci				struct icp_qat_fw_auth_desc **desc)
12228c2ecf20Sopenharmony_ci{
12238c2ecf20Sopenharmony_ci	struct icp_qat_css_hdr *css_hdr = (struct icp_qat_css_hdr *)image;
12248c2ecf20Sopenharmony_ci	struct icp_qat_fw_auth_desc *auth_desc;
12258c2ecf20Sopenharmony_ci	struct icp_qat_auth_chunk *auth_chunk;
12268c2ecf20Sopenharmony_ci	u64 virt_addr,  bus_addr, virt_base;
12278c2ecf20Sopenharmony_ci	unsigned int length, simg_offset = sizeof(*auth_chunk);
12288c2ecf20Sopenharmony_ci	struct icp_firml_dram_desc img_desc;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (size > (ICP_QAT_AE_IMG_OFFSET + ICP_QAT_CSS_MAX_IMAGE_LEN)) {
12318c2ecf20Sopenharmony_ci		pr_err("QAT: error, input image size overflow %d\n", size);
12328c2ecf20Sopenharmony_ci		return -EINVAL;
12338c2ecf20Sopenharmony_ci	}
12348c2ecf20Sopenharmony_ci	length = (css_hdr->fw_type == CSS_AE_FIRMWARE) ?
12358c2ecf20Sopenharmony_ci		 ICP_QAT_CSS_AE_SIMG_LEN + simg_offset :
12368c2ecf20Sopenharmony_ci		 size + ICP_QAT_CSS_FWSK_PAD_LEN + simg_offset;
12378c2ecf20Sopenharmony_ci	if (qat_uclo_simg_alloc(handle, &img_desc, length)) {
12388c2ecf20Sopenharmony_ci		pr_err("QAT: error, allocate continuous dram fail\n");
12398c2ecf20Sopenharmony_ci		return -ENOMEM;
12408c2ecf20Sopenharmony_ci	}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	auth_chunk = img_desc.dram_base_addr_v;
12438c2ecf20Sopenharmony_ci	auth_chunk->chunk_size = img_desc.dram_size;
12448c2ecf20Sopenharmony_ci	auth_chunk->chunk_bus_addr = img_desc.dram_bus_addr;
12458c2ecf20Sopenharmony_ci	virt_base = (uintptr_t)img_desc.dram_base_addr_v + simg_offset;
12468c2ecf20Sopenharmony_ci	bus_addr  = img_desc.dram_bus_addr + simg_offset;
12478c2ecf20Sopenharmony_ci	auth_desc = img_desc.dram_base_addr_v;
12488c2ecf20Sopenharmony_ci	auth_desc->css_hdr_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
12498c2ecf20Sopenharmony_ci	auth_desc->css_hdr_low = (unsigned int)bus_addr;
12508c2ecf20Sopenharmony_ci	virt_addr = virt_base;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	memcpy((void *)(uintptr_t)virt_addr, image, sizeof(*css_hdr));
12538c2ecf20Sopenharmony_ci	/* pub key */
12548c2ecf20Sopenharmony_ci	bus_addr = ADD_ADDR(auth_desc->css_hdr_high, auth_desc->css_hdr_low) +
12558c2ecf20Sopenharmony_ci			   sizeof(*css_hdr);
12568c2ecf20Sopenharmony_ci	virt_addr = virt_addr + sizeof(*css_hdr);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	auth_desc->fwsk_pub_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
12598c2ecf20Sopenharmony_ci	auth_desc->fwsk_pub_low = (unsigned int)bus_addr;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	memcpy((void *)(uintptr_t)virt_addr,
12628c2ecf20Sopenharmony_ci	       (void *)(image + sizeof(*css_hdr)),
12638c2ecf20Sopenharmony_ci	       ICP_QAT_CSS_FWSK_MODULUS_LEN);
12648c2ecf20Sopenharmony_ci	/* padding */
12658c2ecf20Sopenharmony_ci	memset((void *)(uintptr_t)(virt_addr + ICP_QAT_CSS_FWSK_MODULUS_LEN),
12668c2ecf20Sopenharmony_ci	       0, ICP_QAT_CSS_FWSK_PAD_LEN);
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	/* exponent */
12698c2ecf20Sopenharmony_ci	memcpy((void *)(uintptr_t)(virt_addr + ICP_QAT_CSS_FWSK_MODULUS_LEN +
12708c2ecf20Sopenharmony_ci	       ICP_QAT_CSS_FWSK_PAD_LEN),
12718c2ecf20Sopenharmony_ci	       (void *)(image + sizeof(*css_hdr) +
12728c2ecf20Sopenharmony_ci			ICP_QAT_CSS_FWSK_MODULUS_LEN),
12738c2ecf20Sopenharmony_ci	       sizeof(unsigned int));
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	/* signature */
12768c2ecf20Sopenharmony_ci	bus_addr = ADD_ADDR(auth_desc->fwsk_pub_high,
12778c2ecf20Sopenharmony_ci			    auth_desc->fwsk_pub_low) +
12788c2ecf20Sopenharmony_ci		   ICP_QAT_CSS_FWSK_PUB_LEN;
12798c2ecf20Sopenharmony_ci	virt_addr = virt_addr + ICP_QAT_CSS_FWSK_PUB_LEN;
12808c2ecf20Sopenharmony_ci	auth_desc->signature_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
12818c2ecf20Sopenharmony_ci	auth_desc->signature_low = (unsigned int)bus_addr;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	memcpy((void *)(uintptr_t)virt_addr,
12848c2ecf20Sopenharmony_ci	       (void *)(image + sizeof(*css_hdr) +
12858c2ecf20Sopenharmony_ci	       ICP_QAT_CSS_FWSK_MODULUS_LEN +
12868c2ecf20Sopenharmony_ci	       ICP_QAT_CSS_FWSK_EXPONENT_LEN),
12878c2ecf20Sopenharmony_ci	       ICP_QAT_CSS_SIGNATURE_LEN);
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	bus_addr = ADD_ADDR(auth_desc->signature_high,
12908c2ecf20Sopenharmony_ci			    auth_desc->signature_low) +
12918c2ecf20Sopenharmony_ci		   ICP_QAT_CSS_SIGNATURE_LEN;
12928c2ecf20Sopenharmony_ci	virt_addr += ICP_QAT_CSS_SIGNATURE_LEN;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	auth_desc->img_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
12958c2ecf20Sopenharmony_ci	auth_desc->img_low = (unsigned int)bus_addr;
12968c2ecf20Sopenharmony_ci	auth_desc->img_len = size - ICP_QAT_AE_IMG_OFFSET;
12978c2ecf20Sopenharmony_ci	memcpy((void *)(uintptr_t)virt_addr,
12988c2ecf20Sopenharmony_ci	       (void *)(image + ICP_QAT_AE_IMG_OFFSET),
12998c2ecf20Sopenharmony_ci	       auth_desc->img_len);
13008c2ecf20Sopenharmony_ci	virt_addr = virt_base;
13018c2ecf20Sopenharmony_ci	/* AE firmware */
13028c2ecf20Sopenharmony_ci	if (((struct icp_qat_css_hdr *)(uintptr_t)virt_addr)->fw_type ==
13038c2ecf20Sopenharmony_ci	    CSS_AE_FIRMWARE) {
13048c2ecf20Sopenharmony_ci		auth_desc->img_ae_mode_data_high = auth_desc->img_high;
13058c2ecf20Sopenharmony_ci		auth_desc->img_ae_mode_data_low = auth_desc->img_low;
13068c2ecf20Sopenharmony_ci		bus_addr = ADD_ADDR(auth_desc->img_ae_mode_data_high,
13078c2ecf20Sopenharmony_ci				    auth_desc->img_ae_mode_data_low) +
13088c2ecf20Sopenharmony_ci			   sizeof(struct icp_qat_simg_ae_mode);
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci		auth_desc->img_ae_init_data_high = (unsigned int)
13118c2ecf20Sopenharmony_ci						 (bus_addr >> BITS_IN_DWORD);
13128c2ecf20Sopenharmony_ci		auth_desc->img_ae_init_data_low = (unsigned int)bus_addr;
13138c2ecf20Sopenharmony_ci		bus_addr += ICP_QAT_SIMG_AE_INIT_SEQ_LEN;
13148c2ecf20Sopenharmony_ci		auth_desc->img_ae_insts_high = (unsigned int)
13158c2ecf20Sopenharmony_ci					     (bus_addr >> BITS_IN_DWORD);
13168c2ecf20Sopenharmony_ci		auth_desc->img_ae_insts_low = (unsigned int)bus_addr;
13178c2ecf20Sopenharmony_ci	} else {
13188c2ecf20Sopenharmony_ci		auth_desc->img_ae_insts_high = auth_desc->img_high;
13198c2ecf20Sopenharmony_ci		auth_desc->img_ae_insts_low = auth_desc->img_low;
13208c2ecf20Sopenharmony_ci	}
13218c2ecf20Sopenharmony_ci	*desc = auth_desc;
13228c2ecf20Sopenharmony_ci	return 0;
13238c2ecf20Sopenharmony_ci}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_cistatic int qat_uclo_load_fw(struct icp_qat_fw_loader_handle *handle,
13268c2ecf20Sopenharmony_ci			    struct icp_qat_fw_auth_desc *desc)
13278c2ecf20Sopenharmony_ci{
13288c2ecf20Sopenharmony_ci	unsigned int i;
13298c2ecf20Sopenharmony_ci	unsigned int fcu_sts;
13308c2ecf20Sopenharmony_ci	struct icp_qat_simg_ae_mode *virt_addr;
13318c2ecf20Sopenharmony_ci	unsigned int fcu_loaded_ae_pos = FCU_LOADED_AE_POS;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	virt_addr = (void *)((uintptr_t)desc +
13348c2ecf20Sopenharmony_ci		     sizeof(struct icp_qat_auth_chunk) +
13358c2ecf20Sopenharmony_ci		     sizeof(struct icp_qat_css_hdr) +
13368c2ecf20Sopenharmony_ci		     ICP_QAT_CSS_FWSK_PUB_LEN +
13378c2ecf20Sopenharmony_ci		     ICP_QAT_CSS_SIGNATURE_LEN);
13388c2ecf20Sopenharmony_ci	for (i = 0; i < handle->hal_handle->ae_max_num; i++) {
13398c2ecf20Sopenharmony_ci		int retry = 0;
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci		if (!((virt_addr->ae_mask >> i) & 0x1))
13428c2ecf20Sopenharmony_ci			continue;
13438c2ecf20Sopenharmony_ci		if (qat_hal_check_ae_active(handle, i)) {
13448c2ecf20Sopenharmony_ci			pr_err("QAT: AE %d is active\n", i);
13458c2ecf20Sopenharmony_ci			return -EINVAL;
13468c2ecf20Sopenharmony_ci		}
13478c2ecf20Sopenharmony_ci		SET_CAP_CSR(handle, FCU_CONTROL,
13488c2ecf20Sopenharmony_ci			    (FCU_CTRL_CMD_LOAD | (i << FCU_CTRL_AE_POS)));
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci		do {
13518c2ecf20Sopenharmony_ci			msleep(FW_AUTH_WAIT_PERIOD);
13528c2ecf20Sopenharmony_ci			fcu_sts = GET_CAP_CSR(handle, FCU_STATUS);
13538c2ecf20Sopenharmony_ci			if (((fcu_sts & FCU_AUTH_STS_MASK) ==
13548c2ecf20Sopenharmony_ci			    FCU_STS_LOAD_DONE) &&
13558c2ecf20Sopenharmony_ci			    ((fcu_sts >> fcu_loaded_ae_pos) & (1 << i)))
13568c2ecf20Sopenharmony_ci				break;
13578c2ecf20Sopenharmony_ci		} while (retry++ < FW_AUTH_MAX_RETRY);
13588c2ecf20Sopenharmony_ci		if (retry > FW_AUTH_MAX_RETRY) {
13598c2ecf20Sopenharmony_ci			pr_err("QAT: firmware load failed timeout %x\n", retry);
13608c2ecf20Sopenharmony_ci			return -EINVAL;
13618c2ecf20Sopenharmony_ci		}
13628c2ecf20Sopenharmony_ci	}
13638c2ecf20Sopenharmony_ci	return 0;
13648c2ecf20Sopenharmony_ci}
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_cistatic int qat_uclo_map_suof_obj(struct icp_qat_fw_loader_handle *handle,
13678c2ecf20Sopenharmony_ci				 void *addr_ptr, int mem_size)
13688c2ecf20Sopenharmony_ci{
13698c2ecf20Sopenharmony_ci	struct icp_qat_suof_handle *suof_handle;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	suof_handle = kzalloc(sizeof(*suof_handle), GFP_KERNEL);
13728c2ecf20Sopenharmony_ci	if (!suof_handle)
13738c2ecf20Sopenharmony_ci		return -ENOMEM;
13748c2ecf20Sopenharmony_ci	handle->sobj_handle = suof_handle;
13758c2ecf20Sopenharmony_ci	if (qat_uclo_map_suof(handle, addr_ptr, mem_size)) {
13768c2ecf20Sopenharmony_ci		qat_uclo_del_suof(handle);
13778c2ecf20Sopenharmony_ci		pr_err("QAT: map SUOF failed\n");
13788c2ecf20Sopenharmony_ci		return -EINVAL;
13798c2ecf20Sopenharmony_ci	}
13808c2ecf20Sopenharmony_ci	return 0;
13818c2ecf20Sopenharmony_ci}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ciint qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle,
13848c2ecf20Sopenharmony_ci		       void *addr_ptr, int mem_size)
13858c2ecf20Sopenharmony_ci{
13868c2ecf20Sopenharmony_ci	struct icp_qat_fw_auth_desc *desc = NULL;
13878c2ecf20Sopenharmony_ci	int status = 0;
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	if (handle->fw_auth) {
13908c2ecf20Sopenharmony_ci		if (!qat_uclo_map_auth_fw(handle, addr_ptr, mem_size, &desc))
13918c2ecf20Sopenharmony_ci			status = qat_uclo_auth_fw(handle, desc);
13928c2ecf20Sopenharmony_ci		qat_uclo_ummap_auth_fw(handle, &desc);
13938c2ecf20Sopenharmony_ci	} else {
13948c2ecf20Sopenharmony_ci		if (handle->pci_dev->device == PCI_DEVICE_ID_INTEL_QAT_C3XXX) {
13958c2ecf20Sopenharmony_ci			pr_err("QAT: C3XXX doesn't support unsigned MMP\n");
13968c2ecf20Sopenharmony_ci			return -EINVAL;
13978c2ecf20Sopenharmony_ci		}
13988c2ecf20Sopenharmony_ci		qat_uclo_wr_sram_by_words(handle, 0, addr_ptr, mem_size);
13998c2ecf20Sopenharmony_ci	}
14008c2ecf20Sopenharmony_ci	return status;
14018c2ecf20Sopenharmony_ci}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_cistatic int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
14048c2ecf20Sopenharmony_ci				void *addr_ptr, int mem_size)
14058c2ecf20Sopenharmony_ci{
14068c2ecf20Sopenharmony_ci	struct icp_qat_uof_filehdr *filehdr;
14078c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *objhdl;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	objhdl = kzalloc(sizeof(*objhdl), GFP_KERNEL);
14108c2ecf20Sopenharmony_ci	if (!objhdl)
14118c2ecf20Sopenharmony_ci		return -ENOMEM;
14128c2ecf20Sopenharmony_ci	objhdl->obj_buf = kmemdup(addr_ptr, mem_size, GFP_KERNEL);
14138c2ecf20Sopenharmony_ci	if (!objhdl->obj_buf)
14148c2ecf20Sopenharmony_ci		goto out_objbuf_err;
14158c2ecf20Sopenharmony_ci	filehdr = (struct icp_qat_uof_filehdr *)objhdl->obj_buf;
14168c2ecf20Sopenharmony_ci	if (qat_uclo_check_uof_format(filehdr))
14178c2ecf20Sopenharmony_ci		goto out_objhdr_err;
14188c2ecf20Sopenharmony_ci	objhdl->obj_hdr = qat_uclo_map_chunk((char *)objhdl->obj_buf, filehdr,
14198c2ecf20Sopenharmony_ci					     ICP_QAT_UOF_OBJS);
14208c2ecf20Sopenharmony_ci	if (!objhdl->obj_hdr) {
14218c2ecf20Sopenharmony_ci		pr_err("QAT: object file chunk is null\n");
14228c2ecf20Sopenharmony_ci		goto out_objhdr_err;
14238c2ecf20Sopenharmony_ci	}
14248c2ecf20Sopenharmony_ci	handle->obj_handle = objhdl;
14258c2ecf20Sopenharmony_ci	if (qat_uclo_parse_uof_obj(handle))
14268c2ecf20Sopenharmony_ci		goto out_overlay_obj_err;
14278c2ecf20Sopenharmony_ci	return 0;
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ciout_overlay_obj_err:
14308c2ecf20Sopenharmony_ci	handle->obj_handle = NULL;
14318c2ecf20Sopenharmony_ci	kfree(objhdl->obj_hdr);
14328c2ecf20Sopenharmony_ciout_objhdr_err:
14338c2ecf20Sopenharmony_ci	kfree(objhdl->obj_buf);
14348c2ecf20Sopenharmony_ciout_objbuf_err:
14358c2ecf20Sopenharmony_ci	kfree(objhdl);
14368c2ecf20Sopenharmony_ci	return -ENOMEM;
14378c2ecf20Sopenharmony_ci}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ciint qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle,
14408c2ecf20Sopenharmony_ci		     void *addr_ptr, int mem_size)
14418c2ecf20Sopenharmony_ci{
14428c2ecf20Sopenharmony_ci	BUILD_BUG_ON(ICP_QAT_UCLO_MAX_AE >=
14438c2ecf20Sopenharmony_ci		     (sizeof(handle->hal_handle->ae_mask) * 8));
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	if (!handle || !addr_ptr || mem_size < 24)
14468c2ecf20Sopenharmony_ci		return -EINVAL;
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci	return (handle->fw_auth) ?
14498c2ecf20Sopenharmony_ci			qat_uclo_map_suof_obj(handle, addr_ptr, mem_size) :
14508c2ecf20Sopenharmony_ci			qat_uclo_map_uof_obj(handle, addr_ptr, mem_size);
14518c2ecf20Sopenharmony_ci}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_civoid qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle)
14548c2ecf20Sopenharmony_ci{
14558c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
14568c2ecf20Sopenharmony_ci	unsigned int a;
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	if (handle->sobj_handle)
14598c2ecf20Sopenharmony_ci		qat_uclo_del_suof(handle);
14608c2ecf20Sopenharmony_ci	if (!obj_handle)
14618c2ecf20Sopenharmony_ci		return;
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	kfree(obj_handle->uword_buf);
14648c2ecf20Sopenharmony_ci	for (a = 0; a < obj_handle->uimage_num; a++)
14658c2ecf20Sopenharmony_ci		kfree(obj_handle->ae_uimage[a].page);
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	for (a = 0; a < handle->hal_handle->ae_max_num; a++)
14688c2ecf20Sopenharmony_ci		qat_uclo_free_ae_data(&obj_handle->ae_data[a]);
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	kfree(obj_handle->obj_hdr);
14718c2ecf20Sopenharmony_ci	kfree(obj_handle->obj_buf);
14728c2ecf20Sopenharmony_ci	kfree(obj_handle);
14738c2ecf20Sopenharmony_ci	handle->obj_handle = NULL;
14748c2ecf20Sopenharmony_ci}
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_cistatic void qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle *obj_handle,
14778c2ecf20Sopenharmony_ci				 struct icp_qat_uclo_encap_page *encap_page,
14788c2ecf20Sopenharmony_ci				 u64 *uword, unsigned int addr_p,
14798c2ecf20Sopenharmony_ci				 unsigned int raddr, u64 fill)
14808c2ecf20Sopenharmony_ci{
14818c2ecf20Sopenharmony_ci	u64 uwrd = 0;
14828c2ecf20Sopenharmony_ci	unsigned int i;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	if (!encap_page) {
14858c2ecf20Sopenharmony_ci		*uword = fill;
14868c2ecf20Sopenharmony_ci		return;
14878c2ecf20Sopenharmony_ci	}
14888c2ecf20Sopenharmony_ci	for (i = 0; i < encap_page->uwblock_num; i++) {
14898c2ecf20Sopenharmony_ci		if (raddr >= encap_page->uwblock[i].start_addr &&
14908c2ecf20Sopenharmony_ci		    raddr <= encap_page->uwblock[i].start_addr +
14918c2ecf20Sopenharmony_ci		    encap_page->uwblock[i].words_num - 1) {
14928c2ecf20Sopenharmony_ci			raddr -= encap_page->uwblock[i].start_addr;
14938c2ecf20Sopenharmony_ci			raddr *= obj_handle->uword_in_bytes;
14948c2ecf20Sopenharmony_ci			memcpy(&uwrd, (void *)(((uintptr_t)
14958c2ecf20Sopenharmony_ci			       encap_page->uwblock[i].micro_words) + raddr),
14968c2ecf20Sopenharmony_ci			       obj_handle->uword_in_bytes);
14978c2ecf20Sopenharmony_ci			uwrd = uwrd & 0xbffffffffffull;
14988c2ecf20Sopenharmony_ci		}
14998c2ecf20Sopenharmony_ci	}
15008c2ecf20Sopenharmony_ci	*uword = uwrd;
15018c2ecf20Sopenharmony_ci	if (*uword == INVLD_UWORD)
15028c2ecf20Sopenharmony_ci		*uword = fill;
15038c2ecf20Sopenharmony_ci}
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_cistatic void qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle,
15068c2ecf20Sopenharmony_ci					struct icp_qat_uclo_encap_page
15078c2ecf20Sopenharmony_ci					*encap_page, unsigned int ae)
15088c2ecf20Sopenharmony_ci{
15098c2ecf20Sopenharmony_ci	unsigned int uw_physical_addr, uw_relative_addr, i, words_num, cpylen;
15108c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
15118c2ecf20Sopenharmony_ci	u64 fill_pat;
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	/* load the page starting at appropriate ustore address */
15148c2ecf20Sopenharmony_ci	/* get fill-pattern from an image -- they are all the same */
15158c2ecf20Sopenharmony_ci	memcpy(&fill_pat, obj_handle->ae_uimage[0].img_ptr->fill_pattern,
15168c2ecf20Sopenharmony_ci	       sizeof(u64));
15178c2ecf20Sopenharmony_ci	uw_physical_addr = encap_page->beg_addr_p;
15188c2ecf20Sopenharmony_ci	uw_relative_addr = 0;
15198c2ecf20Sopenharmony_ci	words_num = encap_page->micro_words_num;
15208c2ecf20Sopenharmony_ci	while (words_num) {
15218c2ecf20Sopenharmony_ci		if (words_num < UWORD_CPYBUF_SIZE)
15228c2ecf20Sopenharmony_ci			cpylen = words_num;
15238c2ecf20Sopenharmony_ci		else
15248c2ecf20Sopenharmony_ci			cpylen = UWORD_CPYBUF_SIZE;
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci		/* load the buffer */
15278c2ecf20Sopenharmony_ci		for (i = 0; i < cpylen; i++)
15288c2ecf20Sopenharmony_ci			qat_uclo_fill_uwords(obj_handle, encap_page,
15298c2ecf20Sopenharmony_ci					     &obj_handle->uword_buf[i],
15308c2ecf20Sopenharmony_ci					     uw_physical_addr + i,
15318c2ecf20Sopenharmony_ci					     uw_relative_addr + i, fill_pat);
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci		/* copy the buffer to ustore */
15348c2ecf20Sopenharmony_ci		qat_hal_wr_uwords(handle, (unsigned char)ae,
15358c2ecf20Sopenharmony_ci				  uw_physical_addr, cpylen,
15368c2ecf20Sopenharmony_ci				  obj_handle->uword_buf);
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci		uw_physical_addr += cpylen;
15398c2ecf20Sopenharmony_ci		uw_relative_addr += cpylen;
15408c2ecf20Sopenharmony_ci		words_num -= cpylen;
15418c2ecf20Sopenharmony_ci	}
15428c2ecf20Sopenharmony_ci}
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_cistatic void qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle *handle,
15458c2ecf20Sopenharmony_ci				    struct icp_qat_uof_image *image)
15468c2ecf20Sopenharmony_ci{
15478c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
15488c2ecf20Sopenharmony_ci	unsigned int ctx_mask, s;
15498c2ecf20Sopenharmony_ci	struct icp_qat_uclo_page *page;
15508c2ecf20Sopenharmony_ci	unsigned char ae;
15518c2ecf20Sopenharmony_ci	int ctx;
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	if (ICP_QAT_CTX_MODE(image->ae_mode) == ICP_QAT_UCLO_MAX_CTX)
15548c2ecf20Sopenharmony_ci		ctx_mask = 0xff;
15558c2ecf20Sopenharmony_ci	else
15568c2ecf20Sopenharmony_ci		ctx_mask = 0x55;
15578c2ecf20Sopenharmony_ci	/* load the default page and set assigned CTX PC
15588c2ecf20Sopenharmony_ci	 * to the entrypoint address */
15598c2ecf20Sopenharmony_ci	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
15608c2ecf20Sopenharmony_ci		if (!test_bit(ae, (unsigned long *)&image->ae_assigned))
15618c2ecf20Sopenharmony_ci			continue;
15628c2ecf20Sopenharmony_ci		/* find the slice to which this image is assigned */
15638c2ecf20Sopenharmony_ci		for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
15648c2ecf20Sopenharmony_ci			if (image->ctx_assigned & obj_handle->ae_data[ae].
15658c2ecf20Sopenharmony_ci			    ae_slices[s].ctx_mask_assigned)
15668c2ecf20Sopenharmony_ci				break;
15678c2ecf20Sopenharmony_ci		}
15688c2ecf20Sopenharmony_ci		if (s >= obj_handle->ae_data[ae].slice_num)
15698c2ecf20Sopenharmony_ci			continue;
15708c2ecf20Sopenharmony_ci		page = obj_handle->ae_data[ae].ae_slices[s].page;
15718c2ecf20Sopenharmony_ci		if (!page->encap_page->def_page)
15728c2ecf20Sopenharmony_ci			continue;
15738c2ecf20Sopenharmony_ci		qat_uclo_wr_uimage_raw_page(handle, page->encap_page, ae);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci		page = obj_handle->ae_data[ae].ae_slices[s].page;
15768c2ecf20Sopenharmony_ci		for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++)
15778c2ecf20Sopenharmony_ci			obj_handle->ae_data[ae].ae_slices[s].cur_page[ctx] =
15788c2ecf20Sopenharmony_ci					(ctx_mask & (1 << ctx)) ? page : NULL;
15798c2ecf20Sopenharmony_ci		qat_hal_set_live_ctx(handle, (unsigned char)ae,
15808c2ecf20Sopenharmony_ci				     image->ctx_assigned);
15818c2ecf20Sopenharmony_ci		qat_hal_set_pc(handle, (unsigned char)ae, image->ctx_assigned,
15828c2ecf20Sopenharmony_ci			       image->entry_address);
15838c2ecf20Sopenharmony_ci	}
15848c2ecf20Sopenharmony_ci}
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_cistatic int qat_uclo_wr_suof_img(struct icp_qat_fw_loader_handle *handle)
15878c2ecf20Sopenharmony_ci{
15888c2ecf20Sopenharmony_ci	unsigned int i;
15898c2ecf20Sopenharmony_ci	struct icp_qat_fw_auth_desc *desc = NULL;
15908c2ecf20Sopenharmony_ci	struct icp_qat_suof_handle *sobj_handle = handle->sobj_handle;
15918c2ecf20Sopenharmony_ci	struct icp_qat_suof_img_hdr *simg_hdr = sobj_handle->img_table.simg_hdr;
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	for (i = 0; i < sobj_handle->img_table.num_simgs; i++) {
15948c2ecf20Sopenharmony_ci		if (qat_uclo_map_auth_fw(handle,
15958c2ecf20Sopenharmony_ci					 (char *)simg_hdr[i].simg_buf,
15968c2ecf20Sopenharmony_ci					 (unsigned int)
15978c2ecf20Sopenharmony_ci					 (simg_hdr[i].simg_len),
15988c2ecf20Sopenharmony_ci					 &desc))
15998c2ecf20Sopenharmony_ci			goto wr_err;
16008c2ecf20Sopenharmony_ci		if (qat_uclo_auth_fw(handle, desc))
16018c2ecf20Sopenharmony_ci			goto wr_err;
16028c2ecf20Sopenharmony_ci		if (qat_uclo_load_fw(handle, desc))
16038c2ecf20Sopenharmony_ci			goto wr_err;
16048c2ecf20Sopenharmony_ci		qat_uclo_ummap_auth_fw(handle, &desc);
16058c2ecf20Sopenharmony_ci	}
16068c2ecf20Sopenharmony_ci	return 0;
16078c2ecf20Sopenharmony_ciwr_err:
16088c2ecf20Sopenharmony_ci	qat_uclo_ummap_auth_fw(handle, &desc);
16098c2ecf20Sopenharmony_ci	return -EINVAL;
16108c2ecf20Sopenharmony_ci}
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_cistatic int qat_uclo_wr_uof_img(struct icp_qat_fw_loader_handle *handle)
16138c2ecf20Sopenharmony_ci{
16148c2ecf20Sopenharmony_ci	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
16158c2ecf20Sopenharmony_ci	unsigned int i;
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	if (qat_uclo_init_globals(handle))
16188c2ecf20Sopenharmony_ci		return -EINVAL;
16198c2ecf20Sopenharmony_ci	for (i = 0; i < obj_handle->uimage_num; i++) {
16208c2ecf20Sopenharmony_ci		if (!obj_handle->ae_uimage[i].img_ptr)
16218c2ecf20Sopenharmony_ci			return -EINVAL;
16228c2ecf20Sopenharmony_ci		if (qat_uclo_init_ustore(handle, &obj_handle->ae_uimage[i]))
16238c2ecf20Sopenharmony_ci			return -EINVAL;
16248c2ecf20Sopenharmony_ci		qat_uclo_wr_uimage_page(handle,
16258c2ecf20Sopenharmony_ci					obj_handle->ae_uimage[i].img_ptr);
16268c2ecf20Sopenharmony_ci	}
16278c2ecf20Sopenharmony_ci	return 0;
16288c2ecf20Sopenharmony_ci}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ciint qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle)
16318c2ecf20Sopenharmony_ci{
16328c2ecf20Sopenharmony_ci	return (handle->fw_auth) ? qat_uclo_wr_suof_img(handle) :
16338c2ecf20Sopenharmony_ci				   qat_uclo_wr_uof_img(handle);
16348c2ecf20Sopenharmony_ci}
1635