xref: /freebsd/sys/dev/qat/qat_common/qat_uclo.c (revision 71625ec9)
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/ctype.h>
1478ee8d1cSJulian Grajkowski #include <sys/kernel.h>
1578ee8d1cSJulian Grajkowski #include <linux/delay.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_hal.h"
2078ee8d1cSJulian Grajkowski #include "icp_qat_fw_loader_handle.h"
2178ee8d1cSJulian Grajkowski 
2278ee8d1cSJulian Grajkowski #define UWORD_CPYBUF_SIZE 1024
2378ee8d1cSJulian Grajkowski #define INVLD_UWORD 0xffffffffffull
2478ee8d1cSJulian Grajkowski #define PID_MINOR_REV 0xf
2578ee8d1cSJulian Grajkowski #define PID_MAJOR_REV (0xf << 4)
2678ee8d1cSJulian Grajkowski #define MAX_UINT32_VAL 0xfffffffful
2778ee8d1cSJulian Grajkowski 
2878ee8d1cSJulian Grajkowski static int
qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle * obj_handle,unsigned int ae,unsigned int image_num)2978ee8d1cSJulian Grajkowski qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle *obj_handle,
3078ee8d1cSJulian Grajkowski 		      unsigned int ae,
3178ee8d1cSJulian Grajkowski 		      unsigned int image_num)
3278ee8d1cSJulian Grajkowski {
3378ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_aedata *ae_data;
3478ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_encapme *encap_image;
3578ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_page *page = NULL;
3678ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_aeslice *ae_slice = NULL;
3778ee8d1cSJulian Grajkowski 
3878ee8d1cSJulian Grajkowski 	ae_data = &obj_handle->ae_data[ae];
3978ee8d1cSJulian Grajkowski 	encap_image = &obj_handle->ae_uimage[image_num];
4078ee8d1cSJulian Grajkowski 	ae_slice = &ae_data->ae_slices[ae_data->slice_num];
4178ee8d1cSJulian Grajkowski 	ae_slice->encap_image = encap_image;
4278ee8d1cSJulian Grajkowski 
4378ee8d1cSJulian Grajkowski 	if (encap_image->img_ptr) {
4478ee8d1cSJulian Grajkowski 		ae_slice->ctx_mask_assigned =
4578ee8d1cSJulian Grajkowski 		    encap_image->img_ptr->ctx_assigned;
4678ee8d1cSJulian Grajkowski 		ae_data->shareable_ustore =
4778ee8d1cSJulian Grajkowski 		    ICP_QAT_SHARED_USTORE_MODE(encap_image->img_ptr->ae_mode);
48a977168cSMichal Gulbicki 		if (obj_handle->prod_type == ICP_QAT_AC_4XXX_A_DEV_TYPE)
49a977168cSMichal Gulbicki 			ae_data->eff_ustore_size = obj_handle->ustore_phy_size;
50a977168cSMichal Gulbicki 		else {
5178ee8d1cSJulian Grajkowski 			ae_data->eff_ustore_size = ae_data->shareable_ustore ?
5278ee8d1cSJulian Grajkowski 			    (obj_handle->ustore_phy_size << 1) :
5378ee8d1cSJulian Grajkowski 			    obj_handle->ustore_phy_size;
54a977168cSMichal Gulbicki 		}
5578ee8d1cSJulian Grajkowski 	} else {
5678ee8d1cSJulian Grajkowski 		ae_slice->ctx_mask_assigned = 0;
5778ee8d1cSJulian Grajkowski 	}
5878ee8d1cSJulian Grajkowski 	ae_slice->region =
5978ee8d1cSJulian Grajkowski 	    malloc(sizeof(*ae_slice->region), M_QAT, M_WAITOK | M_ZERO);
6078ee8d1cSJulian Grajkowski 	ae_slice->page =
6178ee8d1cSJulian Grajkowski 	    malloc(sizeof(*ae_slice->page), M_QAT, M_WAITOK | M_ZERO);
6278ee8d1cSJulian Grajkowski 	page = ae_slice->page;
6378ee8d1cSJulian Grajkowski 	page->encap_page = encap_image->page;
6478ee8d1cSJulian Grajkowski 	ae_slice->page->region = ae_slice->region;
6578ee8d1cSJulian Grajkowski 	ae_data->slice_num++;
6678ee8d1cSJulian Grajkowski 	return 0;
6778ee8d1cSJulian Grajkowski }
6878ee8d1cSJulian Grajkowski 
6978ee8d1cSJulian Grajkowski static int
qat_uclo_free_ae_data(struct icp_qat_uclo_aedata * ae_data)7078ee8d1cSJulian Grajkowski qat_uclo_free_ae_data(struct icp_qat_uclo_aedata *ae_data)
7178ee8d1cSJulian Grajkowski {
7278ee8d1cSJulian Grajkowski 	unsigned int i;
7378ee8d1cSJulian Grajkowski 
7478ee8d1cSJulian Grajkowski 	if (!ae_data) {
7578ee8d1cSJulian Grajkowski 		pr_err("QAT: bad argument, ae_data is NULL\n ");
7678ee8d1cSJulian Grajkowski 		return EINVAL;
7778ee8d1cSJulian Grajkowski 	}
7878ee8d1cSJulian Grajkowski 
7978ee8d1cSJulian Grajkowski 	for (i = 0; i < ae_data->slice_num; i++) {
8078ee8d1cSJulian Grajkowski 		free(ae_data->ae_slices[i].region, M_QAT);
8178ee8d1cSJulian Grajkowski 		ae_data->ae_slices[i].region = NULL;
8278ee8d1cSJulian Grajkowski 		free(ae_data->ae_slices[i].page, M_QAT);
8378ee8d1cSJulian Grajkowski 		ae_data->ae_slices[i].page = NULL;
8478ee8d1cSJulian Grajkowski 	}
8578ee8d1cSJulian Grajkowski 	return 0;
8678ee8d1cSJulian Grajkowski }
8778ee8d1cSJulian Grajkowski 
8878ee8d1cSJulian Grajkowski static char *
qat_uclo_get_string(struct icp_qat_uof_strtable * str_table,unsigned int str_offset)8978ee8d1cSJulian Grajkowski qat_uclo_get_string(struct icp_qat_uof_strtable *str_table,
9078ee8d1cSJulian Grajkowski 		    unsigned int str_offset)
9178ee8d1cSJulian Grajkowski {
9278ee8d1cSJulian Grajkowski 	if (!str_table->table_len || str_offset > str_table->table_len)
9378ee8d1cSJulian Grajkowski 		return NULL;
9478ee8d1cSJulian Grajkowski 	return (char *)(((uintptr_t)(str_table->strings)) + str_offset);
9578ee8d1cSJulian Grajkowski }
9678ee8d1cSJulian Grajkowski 
9778ee8d1cSJulian Grajkowski static int
qat_uclo_check_uof_format(struct icp_qat_uof_filehdr * hdr)9878ee8d1cSJulian Grajkowski qat_uclo_check_uof_format(struct icp_qat_uof_filehdr *hdr)
9978ee8d1cSJulian Grajkowski {
10078ee8d1cSJulian Grajkowski 	int maj = hdr->maj_ver & 0xff;
10178ee8d1cSJulian Grajkowski 	int min = hdr->min_ver & 0xff;
10278ee8d1cSJulian Grajkowski 
10378ee8d1cSJulian Grajkowski 	if (hdr->file_id != ICP_QAT_UOF_FID) {
10478ee8d1cSJulian Grajkowski 		pr_err("QAT: Invalid header 0x%x\n", hdr->file_id);
10578ee8d1cSJulian Grajkowski 		return EINVAL;
10678ee8d1cSJulian Grajkowski 	}
10778ee8d1cSJulian Grajkowski 	if (min != ICP_QAT_UOF_MINVER || maj != ICP_QAT_UOF_MAJVER) {
10878ee8d1cSJulian Grajkowski 		pr_err("QAT: bad UOF version, major 0x%x, minor 0x%x\n",
10978ee8d1cSJulian Grajkowski 		       maj,
11078ee8d1cSJulian Grajkowski 		       min);
11178ee8d1cSJulian Grajkowski 		return EINVAL;
11278ee8d1cSJulian Grajkowski 	}
11378ee8d1cSJulian Grajkowski 	return 0;
11478ee8d1cSJulian Grajkowski }
11578ee8d1cSJulian Grajkowski 
11678ee8d1cSJulian Grajkowski static int
qat_uclo_check_suof_format(const struct icp_qat_suof_filehdr * suof_hdr)11778ee8d1cSJulian Grajkowski qat_uclo_check_suof_format(const struct icp_qat_suof_filehdr *suof_hdr)
11878ee8d1cSJulian Grajkowski {
11978ee8d1cSJulian Grajkowski 	int maj = suof_hdr->maj_ver & 0xff;
12078ee8d1cSJulian Grajkowski 	int min = suof_hdr->min_ver & 0xff;
12178ee8d1cSJulian Grajkowski 
12278ee8d1cSJulian Grajkowski 	if (suof_hdr->file_id != ICP_QAT_SUOF_FID) {
12378ee8d1cSJulian Grajkowski 		pr_err("QAT: invalid header 0x%x\n", suof_hdr->file_id);
12478ee8d1cSJulian Grajkowski 		return EINVAL;
12578ee8d1cSJulian Grajkowski 	}
12678ee8d1cSJulian Grajkowski 	if (suof_hdr->fw_type != 0) {
12778ee8d1cSJulian Grajkowski 		pr_err("QAT: unsupported firmware type\n");
12878ee8d1cSJulian Grajkowski 		return EINVAL;
12978ee8d1cSJulian Grajkowski 	}
13078ee8d1cSJulian Grajkowski 	if (suof_hdr->num_chunks <= 0x1) {
13178ee8d1cSJulian Grajkowski 		pr_err("QAT: SUOF chunk amount is incorrect\n");
13278ee8d1cSJulian Grajkowski 		return EINVAL;
13378ee8d1cSJulian Grajkowski 	}
13478ee8d1cSJulian Grajkowski 	if (maj != ICP_QAT_SUOF_MAJVER || min != ICP_QAT_SUOF_MINVER) {
13578ee8d1cSJulian Grajkowski 		pr_err("QAT: bad SUOF version, major 0x%x, minor 0x%x\n",
13678ee8d1cSJulian Grajkowski 		       maj,
13778ee8d1cSJulian Grajkowski 		       min);
13878ee8d1cSJulian Grajkowski 		return EINVAL;
13978ee8d1cSJulian Grajkowski 	}
14078ee8d1cSJulian Grajkowski 	return 0;
14178ee8d1cSJulian Grajkowski }
14278ee8d1cSJulian Grajkowski 
14378ee8d1cSJulian Grajkowski static int
qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle * handle,unsigned int addr,const unsigned int * val,unsigned int num_in_bytes)14478ee8d1cSJulian Grajkowski qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle *handle,
14578ee8d1cSJulian Grajkowski 			  unsigned int addr,
14678ee8d1cSJulian Grajkowski 			  const unsigned int *val,
14778ee8d1cSJulian Grajkowski 			  unsigned int num_in_bytes)
14878ee8d1cSJulian Grajkowski {
14978ee8d1cSJulian Grajkowski 	unsigned int outval;
15078ee8d1cSJulian Grajkowski 	const unsigned char *ptr = (const unsigned char *)val;
15178ee8d1cSJulian Grajkowski 
15278ee8d1cSJulian Grajkowski 	if (num_in_bytes > handle->hal_sram_size) {
15378ee8d1cSJulian Grajkowski 		pr_err("QAT: error, mmp size overflow %d\n", num_in_bytes);
15478ee8d1cSJulian Grajkowski 		return EINVAL;
15578ee8d1cSJulian Grajkowski 	}
15678ee8d1cSJulian Grajkowski 	while (num_in_bytes) {
15778ee8d1cSJulian Grajkowski 		memcpy(&outval, ptr, 4);
15878ee8d1cSJulian Grajkowski 		SRAM_WRITE(handle, addr, outval);
15978ee8d1cSJulian Grajkowski 		num_in_bytes -= 4;
16078ee8d1cSJulian Grajkowski 		ptr += 4;
16178ee8d1cSJulian Grajkowski 		addr += 4;
16278ee8d1cSJulian Grajkowski 	}
16378ee8d1cSJulian Grajkowski 	return 0;
16478ee8d1cSJulian Grajkowski }
16578ee8d1cSJulian Grajkowski 
16678ee8d1cSJulian Grajkowski static void
qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle * handle,unsigned char ae,unsigned int addr,unsigned int * val,unsigned int num_in_bytes)16778ee8d1cSJulian Grajkowski qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle *handle,
16878ee8d1cSJulian Grajkowski 			  unsigned char ae,
16978ee8d1cSJulian Grajkowski 			  unsigned int addr,
17078ee8d1cSJulian Grajkowski 			  unsigned int *val,
17178ee8d1cSJulian Grajkowski 			  unsigned int num_in_bytes)
17278ee8d1cSJulian Grajkowski {
17378ee8d1cSJulian Grajkowski 	unsigned int outval;
17478ee8d1cSJulian Grajkowski 	unsigned char *ptr = (unsigned char *)val;
17578ee8d1cSJulian Grajkowski 
17678ee8d1cSJulian Grajkowski 	addr >>= 0x2; /* convert to uword address */
17778ee8d1cSJulian Grajkowski 
17878ee8d1cSJulian Grajkowski 	while (num_in_bytes) {
17978ee8d1cSJulian Grajkowski 		memcpy(&outval, ptr, 4);
18078ee8d1cSJulian Grajkowski 		qat_hal_wr_umem(handle, ae, addr++, 1, &outval);
18178ee8d1cSJulian Grajkowski 		num_in_bytes -= 4;
18278ee8d1cSJulian Grajkowski 		ptr += 4;
18378ee8d1cSJulian Grajkowski 	}
18478ee8d1cSJulian Grajkowski }
18578ee8d1cSJulian Grajkowski 
18678ee8d1cSJulian Grajkowski static void
qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle * handle,unsigned char ae,struct icp_qat_uof_batch_init * umem_init_header)18778ee8d1cSJulian Grajkowski qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle *handle,
18878ee8d1cSJulian Grajkowski 		       unsigned char ae,
18978ee8d1cSJulian Grajkowski 		       struct icp_qat_uof_batch_init *umem_init_header)
19078ee8d1cSJulian Grajkowski {
19178ee8d1cSJulian Grajkowski 	struct icp_qat_uof_batch_init *umem_init;
19278ee8d1cSJulian Grajkowski 
19378ee8d1cSJulian Grajkowski 	if (!umem_init_header)
19478ee8d1cSJulian Grajkowski 		return;
19578ee8d1cSJulian Grajkowski 	umem_init = umem_init_header->next;
19678ee8d1cSJulian Grajkowski 	while (umem_init) {
19778ee8d1cSJulian Grajkowski 		unsigned int addr, *value, size;
19878ee8d1cSJulian Grajkowski 
19978ee8d1cSJulian Grajkowski 		ae = umem_init->ae;
20078ee8d1cSJulian Grajkowski 		addr = umem_init->addr;
20178ee8d1cSJulian Grajkowski 		value = umem_init->value;
20278ee8d1cSJulian Grajkowski 		size = umem_init->size;
20378ee8d1cSJulian Grajkowski 		qat_uclo_wr_umem_by_words(handle, ae, addr, value, size);
20478ee8d1cSJulian Grajkowski 		umem_init = umem_init->next;
20578ee8d1cSJulian Grajkowski 	}
20678ee8d1cSJulian Grajkowski }
20778ee8d1cSJulian Grajkowski 
20878ee8d1cSJulian Grajkowski static void
qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_batch_init ** base)20978ee8d1cSJulian Grajkowski qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,
21078ee8d1cSJulian Grajkowski 				 struct icp_qat_uof_batch_init **base)
21178ee8d1cSJulian Grajkowski {
21278ee8d1cSJulian Grajkowski 	struct icp_qat_uof_batch_init *umem_init;
21378ee8d1cSJulian Grajkowski 
21478ee8d1cSJulian Grajkowski 	umem_init = *base;
21578ee8d1cSJulian Grajkowski 	while (umem_init) {
21678ee8d1cSJulian Grajkowski 		struct icp_qat_uof_batch_init *pre;
21778ee8d1cSJulian Grajkowski 
21878ee8d1cSJulian Grajkowski 		pre = umem_init;
21978ee8d1cSJulian Grajkowski 		umem_init = umem_init->next;
22078ee8d1cSJulian Grajkowski 		free(pre, M_QAT);
22178ee8d1cSJulian Grajkowski 	}
22278ee8d1cSJulian Grajkowski 	*base = NULL;
22378ee8d1cSJulian Grajkowski }
22478ee8d1cSJulian Grajkowski 
22578ee8d1cSJulian Grajkowski static int
qat_uclo_parse_num(char * str,unsigned int * num)22678ee8d1cSJulian Grajkowski qat_uclo_parse_num(char *str, unsigned int *num)
22778ee8d1cSJulian Grajkowski {
22878ee8d1cSJulian Grajkowski 	char buf[16] = { 0 };
22978ee8d1cSJulian Grajkowski 	unsigned long ae = 0;
23078ee8d1cSJulian Grajkowski 	int i;
23178ee8d1cSJulian Grajkowski 
23278ee8d1cSJulian Grajkowski 	strncpy(buf, str, 15);
23378ee8d1cSJulian Grajkowski 	for (i = 0; i < 16; i++) {
23478ee8d1cSJulian Grajkowski 		if (!isdigit(buf[i])) {
23578ee8d1cSJulian Grajkowski 			buf[i] = '\0';
23678ee8d1cSJulian Grajkowski 			break;
23778ee8d1cSJulian Grajkowski 		}
23878ee8d1cSJulian Grajkowski 	}
23978ee8d1cSJulian Grajkowski 	if ((compat_strtoul(buf, 10, &ae)))
24078ee8d1cSJulian Grajkowski 		return EFAULT;
24178ee8d1cSJulian Grajkowski 
24278ee8d1cSJulian Grajkowski 	if (ae > MAX_UINT32_VAL)
24378ee8d1cSJulian Grajkowski 		return EFAULT;
24478ee8d1cSJulian Grajkowski 
24578ee8d1cSJulian Grajkowski 	*num = (unsigned int)ae;
24678ee8d1cSJulian Grajkowski 	return 0;
24778ee8d1cSJulian Grajkowski }
24878ee8d1cSJulian Grajkowski 
24978ee8d1cSJulian Grajkowski static int
qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_initmem * init_mem,unsigned int size_range,unsigned int * ae)25078ee8d1cSJulian Grajkowski qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle *handle,
25178ee8d1cSJulian Grajkowski 			  struct icp_qat_uof_initmem *init_mem,
25278ee8d1cSJulian Grajkowski 			  unsigned int size_range,
25378ee8d1cSJulian Grajkowski 			  unsigned int *ae)
25478ee8d1cSJulian Grajkowski {
25578ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
25678ee8d1cSJulian Grajkowski 	char *str;
25778ee8d1cSJulian Grajkowski 
25878ee8d1cSJulian Grajkowski 	if ((init_mem->addr + init_mem->num_in_bytes) > (size_range << 0x2)) {
25978ee8d1cSJulian Grajkowski 		pr_err("QAT: initmem is out of range");
26078ee8d1cSJulian Grajkowski 		return EINVAL;
26178ee8d1cSJulian Grajkowski 	}
26278ee8d1cSJulian Grajkowski 	if (init_mem->scope != ICP_QAT_UOF_LOCAL_SCOPE) {
26378ee8d1cSJulian Grajkowski 		pr_err("QAT: Memory scope for init_mem error\n");
26478ee8d1cSJulian Grajkowski 		return EINVAL;
26578ee8d1cSJulian Grajkowski 	}
26678ee8d1cSJulian Grajkowski 	str = qat_uclo_get_string(&obj_handle->str_table, init_mem->sym_name);
26778ee8d1cSJulian Grajkowski 	if (!str) {
26878ee8d1cSJulian Grajkowski 		pr_err("QAT: AE name assigned in UOF init table is NULL\n");
26978ee8d1cSJulian Grajkowski 		return EINVAL;
27078ee8d1cSJulian Grajkowski 	}
27178ee8d1cSJulian Grajkowski 	if (qat_uclo_parse_num(str, ae)) {
27278ee8d1cSJulian Grajkowski 		pr_err("QAT: Parse num for AE number failed\n");
27378ee8d1cSJulian Grajkowski 		return EINVAL;
27478ee8d1cSJulian Grajkowski 	}
27578ee8d1cSJulian Grajkowski 	if (*ae >= ICP_QAT_UCLO_MAX_AE) {
27678ee8d1cSJulian Grajkowski 		pr_err("QAT: ae %d out of range\n", *ae);
27778ee8d1cSJulian Grajkowski 		return EINVAL;
27878ee8d1cSJulian Grajkowski 	}
27978ee8d1cSJulian Grajkowski 	return 0;
28078ee8d1cSJulian Grajkowski }
28178ee8d1cSJulian Grajkowski 
28278ee8d1cSJulian Grajkowski static int
qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_initmem * init_mem,unsigned int ae,struct icp_qat_uof_batch_init ** init_tab_base)28378ee8d1cSJulian Grajkowski qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle *handle,
28478ee8d1cSJulian Grajkowski 				struct icp_qat_uof_initmem *init_mem,
28578ee8d1cSJulian Grajkowski 				unsigned int ae,
28678ee8d1cSJulian Grajkowski 				struct icp_qat_uof_batch_init **init_tab_base)
28778ee8d1cSJulian Grajkowski {
28878ee8d1cSJulian Grajkowski 	struct icp_qat_uof_batch_init *init_header, *tail;
28978ee8d1cSJulian Grajkowski 	struct icp_qat_uof_batch_init *mem_init, *tail_old;
29078ee8d1cSJulian Grajkowski 	struct icp_qat_uof_memvar_attr *mem_val_attr;
29178ee8d1cSJulian Grajkowski 	unsigned int i = 0;
29278ee8d1cSJulian Grajkowski 
29378ee8d1cSJulian Grajkowski 	mem_val_attr =
29478ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_memvar_attr *)((uintptr_t)init_mem +
29578ee8d1cSJulian Grajkowski 					       sizeof(
29678ee8d1cSJulian Grajkowski 						   struct icp_qat_uof_initmem));
29778ee8d1cSJulian Grajkowski 
29878ee8d1cSJulian Grajkowski 	init_header = *init_tab_base;
29978ee8d1cSJulian Grajkowski 	if (!init_header) {
30078ee8d1cSJulian Grajkowski 		init_header =
30178ee8d1cSJulian Grajkowski 		    malloc(sizeof(*init_header), M_QAT, M_WAITOK | M_ZERO);
30278ee8d1cSJulian Grajkowski 		init_header->size = 1;
30378ee8d1cSJulian Grajkowski 		*init_tab_base = init_header;
30478ee8d1cSJulian Grajkowski 	}
30578ee8d1cSJulian Grajkowski 	tail_old = init_header;
30678ee8d1cSJulian Grajkowski 	while (tail_old->next)
30778ee8d1cSJulian Grajkowski 		tail_old = tail_old->next;
30878ee8d1cSJulian Grajkowski 	tail = tail_old;
30978ee8d1cSJulian Grajkowski 	for (i = 0; i < init_mem->val_attr_num; i++) {
31078ee8d1cSJulian Grajkowski 		mem_init = malloc(sizeof(*mem_init), M_QAT, M_WAITOK | M_ZERO);
31178ee8d1cSJulian Grajkowski 		mem_init->ae = ae;
31278ee8d1cSJulian Grajkowski 		mem_init->addr = init_mem->addr + mem_val_attr->offset_in_byte;
31378ee8d1cSJulian Grajkowski 		mem_init->value = &mem_val_attr->value;
31478ee8d1cSJulian Grajkowski 		mem_init->size = 4;
31578ee8d1cSJulian Grajkowski 		mem_init->next = NULL;
31678ee8d1cSJulian Grajkowski 		tail->next = mem_init;
31778ee8d1cSJulian Grajkowski 		tail = mem_init;
31878ee8d1cSJulian Grajkowski 		init_header->size += qat_hal_get_ins_num();
31978ee8d1cSJulian Grajkowski 		mem_val_attr++;
32078ee8d1cSJulian Grajkowski 	}
32178ee8d1cSJulian Grajkowski 	return 0;
32278ee8d1cSJulian Grajkowski }
32378ee8d1cSJulian Grajkowski 
32478ee8d1cSJulian Grajkowski static int
qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_initmem * init_mem)32578ee8d1cSJulian Grajkowski qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle *handle,
32678ee8d1cSJulian Grajkowski 		       struct icp_qat_uof_initmem *init_mem)
32778ee8d1cSJulian Grajkowski {
32878ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
32978ee8d1cSJulian Grajkowski 	unsigned int ae;
330a977168cSMichal Gulbicki 	unsigned int lmem;
33178ee8d1cSJulian Grajkowski 
332a977168cSMichal Gulbicki 	lmem = IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev))) ?
333a977168cSMichal Gulbicki 	    ICP_QAT_UCLO_MAX_LMEM_REG_2X :
334a977168cSMichal Gulbicki 	    ICP_QAT_UCLO_MAX_LMEM_REG;
335a977168cSMichal Gulbicki 
336a977168cSMichal Gulbicki 	if (qat_uclo_fetch_initmem_ae(handle, init_mem, lmem, &ae))
33778ee8d1cSJulian Grajkowski 		return EINVAL;
33878ee8d1cSJulian Grajkowski 	if (qat_uclo_create_batch_init_list(
33978ee8d1cSJulian Grajkowski 		handle, init_mem, ae, &obj_handle->lm_init_tab[ae]))
34078ee8d1cSJulian Grajkowski 		return EINVAL;
34178ee8d1cSJulian Grajkowski 	return 0;
34278ee8d1cSJulian Grajkowski }
34378ee8d1cSJulian Grajkowski 
34478ee8d1cSJulian Grajkowski static int
qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_initmem * init_mem)34578ee8d1cSJulian Grajkowski qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
34678ee8d1cSJulian Grajkowski 		       struct icp_qat_uof_initmem *init_mem)
34778ee8d1cSJulian Grajkowski {
34878ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
34978ee8d1cSJulian Grajkowski 	unsigned int ae, ustore_size, uaddr, i;
35078ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_aedata *aed;
35178ee8d1cSJulian Grajkowski 
35278ee8d1cSJulian Grajkowski 	ustore_size = obj_handle->ustore_phy_size;
35378ee8d1cSJulian Grajkowski 	if (qat_uclo_fetch_initmem_ae(handle, init_mem, ustore_size, &ae))
35478ee8d1cSJulian Grajkowski 		return EINVAL;
35578ee8d1cSJulian Grajkowski 	if (qat_uclo_create_batch_init_list(
35678ee8d1cSJulian Grajkowski 		handle, init_mem, ae, &obj_handle->umem_init_tab[ae]))
35778ee8d1cSJulian Grajkowski 		return EINVAL;
35878ee8d1cSJulian Grajkowski 	/* set the highest ustore address referenced */
35978ee8d1cSJulian Grajkowski 	uaddr = (init_mem->addr + init_mem->num_in_bytes) >> 0x2;
36078ee8d1cSJulian Grajkowski 	aed = &obj_handle->ae_data[ae];
36178ee8d1cSJulian Grajkowski 	for (i = 0; i < aed->slice_num; i++) {
36278ee8d1cSJulian Grajkowski 		if (aed->ae_slices[i].encap_image->uwords_num < uaddr)
36378ee8d1cSJulian Grajkowski 			aed->ae_slices[i].encap_image->uwords_num = uaddr;
36478ee8d1cSJulian Grajkowski 	}
36578ee8d1cSJulian Grajkowski 	return 0;
36678ee8d1cSJulian Grajkowski }
36778ee8d1cSJulian Grajkowski 
36878ee8d1cSJulian Grajkowski #define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000
36978ee8d1cSJulian Grajkowski static int
qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_initmem * init_mem)37078ee8d1cSJulian Grajkowski qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
37178ee8d1cSJulian Grajkowski 			struct icp_qat_uof_initmem *init_mem)
37278ee8d1cSJulian Grajkowski {
37378ee8d1cSJulian Grajkowski 	switch (init_mem->region) {
37478ee8d1cSJulian Grajkowski 	case ICP_QAT_UOF_LMEM_REGION:
37578ee8d1cSJulian Grajkowski 		if (qat_uclo_init_lmem_seg(handle, init_mem))
37678ee8d1cSJulian Grajkowski 			return EINVAL;
37778ee8d1cSJulian Grajkowski 		break;
37878ee8d1cSJulian Grajkowski 	case ICP_QAT_UOF_UMEM_REGION:
37978ee8d1cSJulian Grajkowski 		if (qat_uclo_init_umem_seg(handle, init_mem))
38078ee8d1cSJulian Grajkowski 			return EINVAL;
38178ee8d1cSJulian Grajkowski 		break;
38278ee8d1cSJulian Grajkowski 	default:
38378ee8d1cSJulian Grajkowski 		pr_err("QAT: initmem region error. region type=0x%x\n",
38478ee8d1cSJulian Grajkowski 		       init_mem->region);
38578ee8d1cSJulian Grajkowski 		return EINVAL;
38678ee8d1cSJulian Grajkowski 	}
38778ee8d1cSJulian Grajkowski 	return 0;
38878ee8d1cSJulian Grajkowski }
38978ee8d1cSJulian Grajkowski 
39078ee8d1cSJulian Grajkowski static int
qat_uclo_init_ustore(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uclo_encapme * image)39178ee8d1cSJulian Grajkowski qat_uclo_init_ustore(struct icp_qat_fw_loader_handle *handle,
39278ee8d1cSJulian Grajkowski 		     struct icp_qat_uclo_encapme *image)
39378ee8d1cSJulian Grajkowski {
39478ee8d1cSJulian Grajkowski 	unsigned int i;
39578ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_encap_page *page;
39678ee8d1cSJulian Grajkowski 	struct icp_qat_uof_image *uof_image;
39778ee8d1cSJulian Grajkowski 	unsigned char ae = 0;
39878ee8d1cSJulian Grajkowski 	unsigned char neigh_ae;
39978ee8d1cSJulian Grajkowski 	unsigned int ustore_size;
40078ee8d1cSJulian Grajkowski 	unsigned int patt_pos;
40178ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
40278ee8d1cSJulian Grajkowski 	uint64_t *fill_data;
40378ee8d1cSJulian Grajkowski 	static unsigned int init[32] = { 0 };
40478ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
40578ee8d1cSJulian Grajkowski 
40678ee8d1cSJulian Grajkowski 	uof_image = image->img_ptr;
40778ee8d1cSJulian Grajkowski 	/*if shared CS mode, the ustore size should be 2*ustore_phy_size*/
40878ee8d1cSJulian Grajkowski 	fill_data = malloc(obj_handle->ustore_phy_size * 2 * sizeof(uint64_t),
40978ee8d1cSJulian Grajkowski 			   M_QAT,
41078ee8d1cSJulian Grajkowski 			   M_WAITOK | M_ZERO);
41178ee8d1cSJulian Grajkowski 	for (i = 0; i < obj_handle->ustore_phy_size * 2; i++)
41278ee8d1cSJulian Grajkowski 		memcpy(&fill_data[i],
41378ee8d1cSJulian Grajkowski 		       &uof_image->fill_pattern,
41478ee8d1cSJulian Grajkowski 		       sizeof(uint64_t));
41578ee8d1cSJulian Grajkowski 	page = image->page;
41678ee8d1cSJulian Grajkowski 
41778ee8d1cSJulian Grajkowski 	for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num)
41878ee8d1cSJulian Grajkowski 	{
41978ee8d1cSJulian Grajkowski 		unsigned long cfg_ae_mask = handle->cfg_ae_mask;
42078ee8d1cSJulian Grajkowski 		unsigned long ae_assigned = uof_image->ae_assigned;
421a977168cSMichal Gulbicki 		const bool gen4 =
422a977168cSMichal Gulbicki 		    IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev)));
42378ee8d1cSJulian Grajkowski 
42478ee8d1cSJulian Grajkowski 		if (!test_bit(ae, &cfg_ae_mask))
42578ee8d1cSJulian Grajkowski 			continue;
42678ee8d1cSJulian Grajkowski 
42778ee8d1cSJulian Grajkowski 		if (!test_bit(ae, &ae_assigned))
42878ee8d1cSJulian Grajkowski 			continue;
42978ee8d1cSJulian Grajkowski 
430a977168cSMichal Gulbicki 		if (obj_handle->ae_data[ae].shareable_ustore && (ae & 1) &&
431a977168cSMichal Gulbicki 		    !gen4) {
43278ee8d1cSJulian Grajkowski 			qat_hal_get_scs_neigh_ae(ae, &neigh_ae);
43378ee8d1cSJulian Grajkowski 
43478ee8d1cSJulian Grajkowski 			if (test_bit(neigh_ae, &ae_assigned))
43578ee8d1cSJulian Grajkowski 				continue;
43678ee8d1cSJulian Grajkowski 		}
43778ee8d1cSJulian Grajkowski 
43878ee8d1cSJulian Grajkowski 		ustore_size = obj_handle->ae_data[ae].eff_ustore_size;
43978ee8d1cSJulian Grajkowski 		patt_pos = page->beg_addr_p + page->micro_words_num;
440a977168cSMichal Gulbicki 		if (obj_handle->ae_data[ae].shareable_ustore && !gen4) {
44178ee8d1cSJulian Grajkowski 			qat_hal_get_scs_neigh_ae(ae, &neigh_ae);
44278ee8d1cSJulian Grajkowski 			if (init[ae] == 0 && page->beg_addr_p != 0) {
44378ee8d1cSJulian Grajkowski 				qat_hal_wr_coalesce_uwords(handle,
44478ee8d1cSJulian Grajkowski 							   (unsigned char)ae,
44578ee8d1cSJulian Grajkowski 							   0,
44678ee8d1cSJulian Grajkowski 							   page->beg_addr_p,
44778ee8d1cSJulian Grajkowski 							   &fill_data[0]);
44878ee8d1cSJulian Grajkowski 			}
44978ee8d1cSJulian Grajkowski 			qat_hal_wr_coalesce_uwords(
45078ee8d1cSJulian Grajkowski 			    handle,
45178ee8d1cSJulian Grajkowski 			    (unsigned char)ae,
45278ee8d1cSJulian Grajkowski 			    patt_pos,
45378ee8d1cSJulian Grajkowski 			    ustore_size - patt_pos,
45478ee8d1cSJulian Grajkowski 			    &fill_data[page->beg_addr_p]);
45578ee8d1cSJulian Grajkowski 			init[ae] = 1;
45678ee8d1cSJulian Grajkowski 			init[neigh_ae] = 1;
45778ee8d1cSJulian Grajkowski 		} else {
458a977168cSMichal Gulbicki 			if (gen4 && (ae % 4 != 0))
459a977168cSMichal Gulbicki 				continue;
460a977168cSMichal Gulbicki 
46178ee8d1cSJulian Grajkowski 			qat_hal_wr_uwords(handle,
46278ee8d1cSJulian Grajkowski 					  (unsigned char)ae,
46378ee8d1cSJulian Grajkowski 					  0,
46478ee8d1cSJulian Grajkowski 					  page->beg_addr_p,
46578ee8d1cSJulian Grajkowski 					  &fill_data[0]);
46678ee8d1cSJulian Grajkowski 			qat_hal_wr_uwords(handle,
46778ee8d1cSJulian Grajkowski 					  (unsigned char)ae,
46878ee8d1cSJulian Grajkowski 					  patt_pos,
46978ee8d1cSJulian Grajkowski 					  ustore_size - patt_pos + 1,
47078ee8d1cSJulian Grajkowski 					  &fill_data[page->beg_addr_p]);
47178ee8d1cSJulian Grajkowski 		}
47278ee8d1cSJulian Grajkowski 	}
47378ee8d1cSJulian Grajkowski 	free(fill_data, M_QAT);
47478ee8d1cSJulian Grajkowski 	return 0;
47578ee8d1cSJulian Grajkowski }
47678ee8d1cSJulian Grajkowski 
47778ee8d1cSJulian Grajkowski static int
qat_uclo_init_memory(struct icp_qat_fw_loader_handle * handle)47878ee8d1cSJulian Grajkowski qat_uclo_init_memory(struct icp_qat_fw_loader_handle *handle)
47978ee8d1cSJulian Grajkowski {
48078ee8d1cSJulian Grajkowski 	int i;
48178ee8d1cSJulian Grajkowski 	int ae = 0;
48278ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
48378ee8d1cSJulian Grajkowski 	struct icp_qat_uof_initmem *initmem = obj_handle->init_mem_tab.init_mem;
48478ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
48578ee8d1cSJulian Grajkowski 
48678ee8d1cSJulian Grajkowski 	for (i = 0; i < obj_handle->init_mem_tab.entry_num; i++) {
48778ee8d1cSJulian Grajkowski 		if (initmem->num_in_bytes) {
48878ee8d1cSJulian Grajkowski 			if (qat_uclo_init_ae_memory(handle, initmem))
48978ee8d1cSJulian Grajkowski 				return EINVAL;
49078ee8d1cSJulian Grajkowski 		}
49178ee8d1cSJulian Grajkowski 		initmem =
49278ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_initmem
49378ee8d1cSJulian Grajkowski 			 *)((uintptr_t)((uintptr_t)initmem +
49478ee8d1cSJulian Grajkowski 					sizeof(struct icp_qat_uof_initmem)) +
49578ee8d1cSJulian Grajkowski 			    (sizeof(struct icp_qat_uof_memvar_attr) *
49678ee8d1cSJulian Grajkowski 			     initmem->val_attr_num));
49778ee8d1cSJulian Grajkowski 	}
49878ee8d1cSJulian Grajkowski 
49978ee8d1cSJulian Grajkowski 	for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num)
50078ee8d1cSJulian Grajkowski 	{
50178ee8d1cSJulian Grajkowski 		if (qat_hal_batch_wr_lm(handle,
50278ee8d1cSJulian Grajkowski 					ae,
50378ee8d1cSJulian Grajkowski 					obj_handle->lm_init_tab[ae])) {
50478ee8d1cSJulian Grajkowski 			pr_err("QAT: fail to batch init lmem for AE %d\n", ae);
50578ee8d1cSJulian Grajkowski 			return EINVAL;
50678ee8d1cSJulian Grajkowski 		}
50778ee8d1cSJulian Grajkowski 		qat_uclo_cleanup_batch_init_list(handle,
50878ee8d1cSJulian Grajkowski 						 &obj_handle->lm_init_tab[ae]);
50978ee8d1cSJulian Grajkowski 		qat_uclo_batch_wr_umem(handle,
51078ee8d1cSJulian Grajkowski 				       ae,
51178ee8d1cSJulian Grajkowski 				       obj_handle->umem_init_tab[ae]);
51278ee8d1cSJulian Grajkowski 		qat_uclo_cleanup_batch_init_list(
51378ee8d1cSJulian Grajkowski 		    handle, &obj_handle->umem_init_tab[ae]);
51478ee8d1cSJulian Grajkowski 	}
51578ee8d1cSJulian Grajkowski 	return 0;
51678ee8d1cSJulian Grajkowski }
51778ee8d1cSJulian Grajkowski 
51878ee8d1cSJulian Grajkowski static void *
qat_uclo_find_chunk(struct icp_qat_uof_objhdr * obj_hdr,char * chunk_id,void * cur)51978ee8d1cSJulian Grajkowski qat_uclo_find_chunk(struct icp_qat_uof_objhdr *obj_hdr,
52078ee8d1cSJulian Grajkowski 		    char *chunk_id,
52178ee8d1cSJulian Grajkowski 		    void *cur)
52278ee8d1cSJulian Grajkowski {
52378ee8d1cSJulian Grajkowski 	int i;
52478ee8d1cSJulian Grajkowski 	struct icp_qat_uof_chunkhdr *chunk_hdr =
52578ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_chunkhdr *)((uintptr_t)obj_hdr +
52678ee8d1cSJulian Grajkowski 					    sizeof(struct icp_qat_uof_objhdr));
52778ee8d1cSJulian Grajkowski 
52878ee8d1cSJulian Grajkowski 	for (i = 0; i < obj_hdr->num_chunks; i++) {
52978ee8d1cSJulian Grajkowski 		if ((cur < (void *)&chunk_hdr[i]) &&
53078ee8d1cSJulian Grajkowski 		    !strncmp(chunk_hdr[i].chunk_id,
53178ee8d1cSJulian Grajkowski 			     chunk_id,
53278ee8d1cSJulian Grajkowski 			     ICP_QAT_UOF_OBJID_LEN)) {
53378ee8d1cSJulian Grajkowski 			return &chunk_hdr[i];
53478ee8d1cSJulian Grajkowski 		}
53578ee8d1cSJulian Grajkowski 	}
53678ee8d1cSJulian Grajkowski 	return NULL;
53778ee8d1cSJulian Grajkowski }
53878ee8d1cSJulian Grajkowski 
53978ee8d1cSJulian Grajkowski static unsigned int
qat_uclo_calc_checksum(unsigned int reg,int ch)54078ee8d1cSJulian Grajkowski qat_uclo_calc_checksum(unsigned int reg, int ch)
54178ee8d1cSJulian Grajkowski {
54278ee8d1cSJulian Grajkowski 	int i;
54378ee8d1cSJulian Grajkowski 	unsigned int topbit = 1 << 0xF;
54478ee8d1cSJulian Grajkowski 	unsigned int inbyte = (unsigned int)((reg >> 0x18) ^ ch);
54578ee8d1cSJulian Grajkowski 
54678ee8d1cSJulian Grajkowski 	reg ^= inbyte << 0x8;
54778ee8d1cSJulian Grajkowski 	for (i = 0; i < 0x8; i++) {
54878ee8d1cSJulian Grajkowski 		if (reg & topbit)
54978ee8d1cSJulian Grajkowski 			reg = (reg << 1) ^ 0x1021;
55078ee8d1cSJulian Grajkowski 		else
55178ee8d1cSJulian Grajkowski 			reg <<= 1;
55278ee8d1cSJulian Grajkowski 	}
55378ee8d1cSJulian Grajkowski 	return reg & 0xFFFF;
55478ee8d1cSJulian Grajkowski }
55578ee8d1cSJulian Grajkowski 
55678ee8d1cSJulian Grajkowski static unsigned int
qat_uclo_calc_str_checksum(const char * ptr,int num)55778ee8d1cSJulian Grajkowski qat_uclo_calc_str_checksum(const char *ptr, int num)
55878ee8d1cSJulian Grajkowski {
55978ee8d1cSJulian Grajkowski 	unsigned int chksum = 0;
56078ee8d1cSJulian Grajkowski 
56178ee8d1cSJulian Grajkowski 	if (ptr)
56278ee8d1cSJulian Grajkowski 		while (num--)
56378ee8d1cSJulian Grajkowski 			chksum = qat_uclo_calc_checksum(chksum, *ptr++);
56478ee8d1cSJulian Grajkowski 	return chksum;
56578ee8d1cSJulian Grajkowski }
56678ee8d1cSJulian Grajkowski 
56778ee8d1cSJulian Grajkowski static struct icp_qat_uclo_objhdr *
qat_uclo_map_chunk(char * buf,struct icp_qat_uof_filehdr * file_hdr,char * chunk_id)56878ee8d1cSJulian Grajkowski qat_uclo_map_chunk(char *buf,
56978ee8d1cSJulian Grajkowski 		   struct icp_qat_uof_filehdr *file_hdr,
57078ee8d1cSJulian Grajkowski 		   char *chunk_id)
57178ee8d1cSJulian Grajkowski {
57278ee8d1cSJulian Grajkowski 	struct icp_qat_uof_filechunkhdr *file_chunk;
57378ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhdr *obj_hdr;
57478ee8d1cSJulian Grajkowski 	char *chunk;
57578ee8d1cSJulian Grajkowski 	int i;
57678ee8d1cSJulian Grajkowski 
57778ee8d1cSJulian Grajkowski 	file_chunk = (struct icp_qat_uof_filechunkhdr
57878ee8d1cSJulian Grajkowski 			  *)(buf + sizeof(struct icp_qat_uof_filehdr));
57978ee8d1cSJulian Grajkowski 	for (i = 0; i < file_hdr->num_chunks; i++) {
58078ee8d1cSJulian Grajkowski 		if (!strncmp(file_chunk->chunk_id,
58178ee8d1cSJulian Grajkowski 			     chunk_id,
58278ee8d1cSJulian Grajkowski 			     ICP_QAT_UOF_OBJID_LEN)) {
58378ee8d1cSJulian Grajkowski 			chunk = buf + file_chunk->offset;
58478ee8d1cSJulian Grajkowski 			if (file_chunk->checksum !=
58578ee8d1cSJulian Grajkowski 			    qat_uclo_calc_str_checksum(chunk, file_chunk->size))
58678ee8d1cSJulian Grajkowski 				break;
58778ee8d1cSJulian Grajkowski 			obj_hdr =
58878ee8d1cSJulian Grajkowski 			    malloc(sizeof(*obj_hdr), M_QAT, M_WAITOK | M_ZERO);
58978ee8d1cSJulian Grajkowski 			obj_hdr->file_buff = chunk;
59078ee8d1cSJulian Grajkowski 			obj_hdr->checksum = file_chunk->checksum;
59178ee8d1cSJulian Grajkowski 			obj_hdr->size = file_chunk->size;
59278ee8d1cSJulian Grajkowski 			return obj_hdr;
59378ee8d1cSJulian Grajkowski 		}
59478ee8d1cSJulian Grajkowski 		file_chunk++;
59578ee8d1cSJulian Grajkowski 	}
59678ee8d1cSJulian Grajkowski 	return NULL;
59778ee8d1cSJulian Grajkowski }
59878ee8d1cSJulian Grajkowski 
59978ee8d1cSJulian Grajkowski static unsigned int
qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj * encap_uof_obj,struct icp_qat_uof_image * image)60078ee8d1cSJulian Grajkowski qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj,
60178ee8d1cSJulian Grajkowski 			    struct icp_qat_uof_image *image)
60278ee8d1cSJulian Grajkowski {
60378ee8d1cSJulian Grajkowski 	struct icp_qat_uof_objtable *uc_var_tab, *imp_var_tab, *imp_expr_tab;
60478ee8d1cSJulian Grajkowski 	struct icp_qat_uof_objtable *neigh_reg_tab;
60578ee8d1cSJulian Grajkowski 	struct icp_qat_uof_code_page *code_page;
60678ee8d1cSJulian Grajkowski 
60778ee8d1cSJulian Grajkowski 	code_page =
60878ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_code_page *)((char *)image +
60978ee8d1cSJulian Grajkowski 					     sizeof(struct icp_qat_uof_image));
61078ee8d1cSJulian Grajkowski 	uc_var_tab =
61178ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
61278ee8d1cSJulian Grajkowski 					    code_page->uc_var_tab_offset);
61378ee8d1cSJulian Grajkowski 	imp_var_tab =
61478ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
61578ee8d1cSJulian Grajkowski 					    code_page->imp_var_tab_offset);
61678ee8d1cSJulian Grajkowski 	imp_expr_tab =
61778ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
61878ee8d1cSJulian Grajkowski 					    code_page->imp_expr_tab_offset);
61978ee8d1cSJulian Grajkowski 	if (uc_var_tab->entry_num || imp_var_tab->entry_num ||
62078ee8d1cSJulian Grajkowski 	    imp_expr_tab->entry_num) {
62178ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF can't contain imported variable to be parsed");
62278ee8d1cSJulian Grajkowski 		return EINVAL;
62378ee8d1cSJulian Grajkowski 	}
62478ee8d1cSJulian Grajkowski 	neigh_reg_tab =
62578ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
62678ee8d1cSJulian Grajkowski 					    code_page->neigh_reg_tab_offset);
62778ee8d1cSJulian Grajkowski 	if (neigh_reg_tab->entry_num) {
62878ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF can't contain neighbor register table\n");
62978ee8d1cSJulian Grajkowski 		return EINVAL;
63078ee8d1cSJulian Grajkowski 	}
63178ee8d1cSJulian Grajkowski 	if (image->numpages > 1) {
63278ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF can't contain multiple pages\n");
63378ee8d1cSJulian Grajkowski 		return EINVAL;
63478ee8d1cSJulian Grajkowski 	}
63578ee8d1cSJulian Grajkowski 	if (RELOADABLE_CTX_SHARED_MODE(image->ae_mode)) {
63678ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF can't use reloadable feature\n");
63778ee8d1cSJulian Grajkowski 		return EFAULT;
63878ee8d1cSJulian Grajkowski 	}
63978ee8d1cSJulian Grajkowski 	return 0;
64078ee8d1cSJulian Grajkowski }
64178ee8d1cSJulian Grajkowski 
64278ee8d1cSJulian Grajkowski static void
qat_uclo_map_image_page(struct icp_qat_uof_encap_obj * encap_uof_obj,struct icp_qat_uof_image * img,struct icp_qat_uclo_encap_page * page)64378ee8d1cSJulian Grajkowski qat_uclo_map_image_page(struct icp_qat_uof_encap_obj *encap_uof_obj,
64478ee8d1cSJulian Grajkowski 			struct icp_qat_uof_image *img,
64578ee8d1cSJulian Grajkowski 			struct icp_qat_uclo_encap_page *page)
64678ee8d1cSJulian Grajkowski {
64778ee8d1cSJulian Grajkowski 	struct icp_qat_uof_code_page *code_page;
64878ee8d1cSJulian Grajkowski 	struct icp_qat_uof_code_area *code_area;
64978ee8d1cSJulian Grajkowski 	struct icp_qat_uof_objtable *uword_block_tab;
65078ee8d1cSJulian Grajkowski 	struct icp_qat_uof_uword_block *uwblock;
65178ee8d1cSJulian Grajkowski 	int i;
65278ee8d1cSJulian Grajkowski 
65378ee8d1cSJulian Grajkowski 	code_page =
65478ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_code_page *)((char *)img +
65578ee8d1cSJulian Grajkowski 					     sizeof(struct icp_qat_uof_image));
65678ee8d1cSJulian Grajkowski 	page->def_page = code_page->def_page;
65778ee8d1cSJulian Grajkowski 	page->page_region = code_page->page_region;
65878ee8d1cSJulian Grajkowski 	page->beg_addr_v = code_page->beg_addr_v;
65978ee8d1cSJulian Grajkowski 	page->beg_addr_p = code_page->beg_addr_p;
66078ee8d1cSJulian Grajkowski 	code_area =
66178ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_code_area *)(encap_uof_obj->beg_uof +
66278ee8d1cSJulian Grajkowski 					     code_page->code_area_offset);
66378ee8d1cSJulian Grajkowski 	page->micro_words_num = code_area->micro_words_num;
66478ee8d1cSJulian Grajkowski 	uword_block_tab =
66578ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
66678ee8d1cSJulian Grajkowski 					    code_area->uword_block_tab);
66778ee8d1cSJulian Grajkowski 	page->uwblock_num = uword_block_tab->entry_num;
66878ee8d1cSJulian Grajkowski 	uwblock = (struct icp_qat_uof_uword_block
66978ee8d1cSJulian Grajkowski 		       *)((char *)uword_block_tab +
67078ee8d1cSJulian Grajkowski 			  sizeof(struct icp_qat_uof_objtable));
67178ee8d1cSJulian Grajkowski 	page->uwblock = (struct icp_qat_uclo_encap_uwblock *)uwblock;
67278ee8d1cSJulian Grajkowski 	for (i = 0; i < uword_block_tab->entry_num; i++)
67378ee8d1cSJulian Grajkowski 		page->uwblock[i].micro_words =
67478ee8d1cSJulian Grajkowski 		    (uintptr_t)encap_uof_obj->beg_uof + uwblock[i].uword_offset;
67578ee8d1cSJulian Grajkowski }
67678ee8d1cSJulian Grajkowski 
67778ee8d1cSJulian Grajkowski static int
qat_uclo_map_uimage(struct icp_qat_uclo_objhandle * obj_handle,struct icp_qat_uclo_encapme * ae_uimage,int max_image)67878ee8d1cSJulian Grajkowski qat_uclo_map_uimage(struct icp_qat_uclo_objhandle *obj_handle,
67978ee8d1cSJulian Grajkowski 		    struct icp_qat_uclo_encapme *ae_uimage,
68078ee8d1cSJulian Grajkowski 		    int max_image)
68178ee8d1cSJulian Grajkowski {
68278ee8d1cSJulian Grajkowski 	int i, j;
68378ee8d1cSJulian Grajkowski 	struct icp_qat_uof_chunkhdr *chunk_hdr = NULL;
68478ee8d1cSJulian Grajkowski 	struct icp_qat_uof_image *image;
68578ee8d1cSJulian Grajkowski 	struct icp_qat_uof_objtable *ae_regtab;
68678ee8d1cSJulian Grajkowski 	struct icp_qat_uof_objtable *init_reg_sym_tab;
68778ee8d1cSJulian Grajkowski 	struct icp_qat_uof_objtable *sbreak_tab;
68878ee8d1cSJulian Grajkowski 	struct icp_qat_uof_encap_obj *encap_uof_obj =
68978ee8d1cSJulian Grajkowski 	    &obj_handle->encap_uof_obj;
69078ee8d1cSJulian Grajkowski 
69178ee8d1cSJulian Grajkowski 	for (j = 0; j < max_image; j++) {
69278ee8d1cSJulian Grajkowski 		chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
69378ee8d1cSJulian Grajkowski 						ICP_QAT_UOF_IMAG,
69478ee8d1cSJulian Grajkowski 						chunk_hdr);
69578ee8d1cSJulian Grajkowski 		if (!chunk_hdr)
69678ee8d1cSJulian Grajkowski 			break;
69778ee8d1cSJulian Grajkowski 		image = (struct icp_qat_uof_image *)(encap_uof_obj->beg_uof +
69878ee8d1cSJulian Grajkowski 						     chunk_hdr->offset);
69978ee8d1cSJulian Grajkowski 		ae_regtab =
70078ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_objtable *)(image->reg_tab_offset +
70178ee8d1cSJulian Grajkowski 						    obj_handle->obj_hdr
70278ee8d1cSJulian Grajkowski 							->file_buff);
70378ee8d1cSJulian Grajkowski 		ae_uimage[j].ae_reg_num = ae_regtab->entry_num;
70478ee8d1cSJulian Grajkowski 		ae_uimage[j].ae_reg =
70578ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_ae_reg
70678ee8d1cSJulian Grajkowski 			 *)(((char *)ae_regtab) +
70778ee8d1cSJulian Grajkowski 			    sizeof(struct icp_qat_uof_objtable));
70878ee8d1cSJulian Grajkowski 		init_reg_sym_tab =
70978ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_objtable *)(image->init_reg_sym_tab +
71078ee8d1cSJulian Grajkowski 						    obj_handle->obj_hdr
71178ee8d1cSJulian Grajkowski 							->file_buff);
71278ee8d1cSJulian Grajkowski 		ae_uimage[j].init_regsym_num = init_reg_sym_tab->entry_num;
71378ee8d1cSJulian Grajkowski 		ae_uimage[j].init_regsym =
71478ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_init_regsym
71578ee8d1cSJulian Grajkowski 			 *)(((char *)init_reg_sym_tab) +
71678ee8d1cSJulian Grajkowski 			    sizeof(struct icp_qat_uof_objtable));
71778ee8d1cSJulian Grajkowski 		sbreak_tab = (struct icp_qat_uof_objtable *)(image->sbreak_tab +
71878ee8d1cSJulian Grajkowski 							     obj_handle->obj_hdr
71978ee8d1cSJulian Grajkowski 								 ->file_buff);
72078ee8d1cSJulian Grajkowski 		ae_uimage[j].sbreak_num = sbreak_tab->entry_num;
72178ee8d1cSJulian Grajkowski 		ae_uimage[j].sbreak =
72278ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_sbreak
72378ee8d1cSJulian Grajkowski 			 *)(((char *)sbreak_tab) +
72478ee8d1cSJulian Grajkowski 			    sizeof(struct icp_qat_uof_objtable));
72578ee8d1cSJulian Grajkowski 		ae_uimage[j].img_ptr = image;
72678ee8d1cSJulian Grajkowski 		if (qat_uclo_check_image_compat(encap_uof_obj, image))
72778ee8d1cSJulian Grajkowski 			goto out_err;
72878ee8d1cSJulian Grajkowski 		ae_uimage[j].page =
72978ee8d1cSJulian Grajkowski 		    malloc(sizeof(struct icp_qat_uclo_encap_page),
73078ee8d1cSJulian Grajkowski 			   M_QAT,
73178ee8d1cSJulian Grajkowski 			   M_WAITOK | M_ZERO);
73278ee8d1cSJulian Grajkowski 		qat_uclo_map_image_page(encap_uof_obj,
73378ee8d1cSJulian Grajkowski 					image,
73478ee8d1cSJulian Grajkowski 					ae_uimage[j].page);
73578ee8d1cSJulian Grajkowski 	}
73678ee8d1cSJulian Grajkowski 	return j;
73778ee8d1cSJulian Grajkowski out_err:
73878ee8d1cSJulian Grajkowski 	for (i = 0; i < j; i++)
73978ee8d1cSJulian Grajkowski 		free(ae_uimage[i].page, M_QAT);
74078ee8d1cSJulian Grajkowski 	return 0;
74178ee8d1cSJulian Grajkowski }
74278ee8d1cSJulian Grajkowski 
74378ee8d1cSJulian Grajkowski static int
UcLo_checkTGroupList2X(struct icp_qat_fw_loader_handle * handle)744a977168cSMichal Gulbicki UcLo_checkTGroupList2X(struct icp_qat_fw_loader_handle *handle)
745a977168cSMichal Gulbicki {
746a977168cSMichal Gulbicki 	int i;
747a977168cSMichal Gulbicki 	unsigned int swAe = 0;
748a977168cSMichal Gulbicki 	unsigned int ii, jj;
749a977168cSMichal Gulbicki 	struct icp_qat_uclo_aedata *ae_data0, *ae_datax;
750a977168cSMichal Gulbicki 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
751a977168cSMichal Gulbicki 
752a977168cSMichal Gulbicki 	for (i = 0; i < obj_handle->uimage_num; i++) {
753a977168cSMichal Gulbicki 		struct icp_qat_uof_image *image =
754a977168cSMichal Gulbicki 		    obj_handle->ae_uimage[i].img_ptr;
755a977168cSMichal Gulbicki 		if (image->numpages > 1) {
756a977168cSMichal Gulbicki 			pr_err(
757a977168cSMichal Gulbicki 			    "Only 1 page is allowed in a UOF for CPM2X; We found %d in %s\n",
758a977168cSMichal Gulbicki 			    image->numpages,
759a977168cSMichal Gulbicki 			    qat_uclo_get_string(&obj_handle->str_table,
760a977168cSMichal Gulbicki 						image->img_name));
761a977168cSMichal Gulbicki 			return EINVAL;
762a977168cSMichal Gulbicki 		}
763a977168cSMichal Gulbicki 	}
764a977168cSMichal Gulbicki 
765a977168cSMichal Gulbicki 	for (swAe = 0;
766a977168cSMichal Gulbicki 	     (swAe < obj_handle->ae_num) && (swAe < ICP_QAT_UCLO_MAX_AE);
767a977168cSMichal Gulbicki 	     swAe += AE_TG_NUM_CPM2X) {
768a977168cSMichal Gulbicki 		if (!qat_hal_check_ae_active(handle, swAe)) {
769a977168cSMichal Gulbicki 			continue;
770a977168cSMichal Gulbicki 		}
771a977168cSMichal Gulbicki 
772a977168cSMichal Gulbicki 		for (ii = swAe; ii < (swAe + AE_TG_NUM_CPM2X); ii++) {
773a977168cSMichal Gulbicki 			ae_data0 = &obj_handle->ae_data[ii];
774a977168cSMichal Gulbicki 			if (ae_data0->slice_num != 1) // not assigned
775a977168cSMichal Gulbicki 				continue;
776a977168cSMichal Gulbicki 
777a977168cSMichal Gulbicki 			for (jj = ii + 1; jj < (swAe + AE_TG_NUM_CPM2X); jj++) {
778a977168cSMichal Gulbicki 				ae_datax = &obj_handle->ae_data[jj];
779a977168cSMichal Gulbicki 				if (ae_datax->slice_num != 1) // not assigned
780a977168cSMichal Gulbicki 					continue;
781a977168cSMichal Gulbicki 				if (ae_data0->ae_slices[0]
782a977168cSMichal Gulbicki 					.encap_image->img_ptr !=
783a977168cSMichal Gulbicki 				    ae_datax->ae_slices[0]
784a977168cSMichal Gulbicki 					.encap_image->img_ptr) {
785a977168cSMichal Gulbicki 					pr_err("Only 1 list is allowed in a ");
786a977168cSMichal Gulbicki 					pr_err("Tgroup for CPM2X;\n");
787a977168cSMichal Gulbicki 					pr_err("ME%d, %d is assigned", ii, jj);
788a977168cSMichal Gulbicki 					pr_err(" different list files\n");
789a977168cSMichal Gulbicki 					return EINVAL;
790a977168cSMichal Gulbicki 				}
791a977168cSMichal Gulbicki 			}
792a977168cSMichal Gulbicki 		}
793a977168cSMichal Gulbicki 	}
794a977168cSMichal Gulbicki 
795a977168cSMichal Gulbicki 	return 0;
796a977168cSMichal Gulbicki }
797a977168cSMichal Gulbicki 
798a977168cSMichal Gulbicki static int
qat_uclo_map_ae(struct icp_qat_fw_loader_handle * handle,int max_ae)79978ee8d1cSJulian Grajkowski qat_uclo_map_ae(struct icp_qat_fw_loader_handle *handle, int max_ae)
80078ee8d1cSJulian Grajkowski {
80178ee8d1cSJulian Grajkowski 	int i;
80278ee8d1cSJulian Grajkowski 	int ae = 0;
80378ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
80478ee8d1cSJulian Grajkowski 	unsigned long cfg_ae_mask = handle->cfg_ae_mask;
80578ee8d1cSJulian Grajkowski 	int mflag = 0;
80678ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
80778ee8d1cSJulian Grajkowski 
80878ee8d1cSJulian Grajkowski 	for_each_set_bit(ae, &ae_mask, max_ae)
80978ee8d1cSJulian Grajkowski 	{
81078ee8d1cSJulian Grajkowski 		if (!test_bit(ae, &cfg_ae_mask))
81178ee8d1cSJulian Grajkowski 			continue;
81278ee8d1cSJulian Grajkowski 
81378ee8d1cSJulian Grajkowski 		for (i = 0; i < obj_handle->uimage_num; i++) {
81478ee8d1cSJulian Grajkowski 			unsigned long ae_assigned =
81578ee8d1cSJulian Grajkowski 			    obj_handle->ae_uimage[i].img_ptr->ae_assigned;
81678ee8d1cSJulian Grajkowski 			if (!test_bit(ae, &ae_assigned))
81778ee8d1cSJulian Grajkowski 				continue;
81878ee8d1cSJulian Grajkowski 			mflag = 1;
81978ee8d1cSJulian Grajkowski 			if (qat_uclo_init_ae_data(obj_handle, ae, i))
82078ee8d1cSJulian Grajkowski 				return EINVAL;
82178ee8d1cSJulian Grajkowski 		}
82278ee8d1cSJulian Grajkowski 	}
823a977168cSMichal Gulbicki 	if (IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
824a977168cSMichal Gulbicki 		if (UcLo_checkTGroupList2X(handle)) {
825a977168cSMichal Gulbicki 			return EINVAL;
826a977168cSMichal Gulbicki 		}
827a977168cSMichal Gulbicki 	}
82878ee8d1cSJulian Grajkowski 	if (!mflag) {
82978ee8d1cSJulian Grajkowski 		pr_err("QAT: uimage uses AE not set");
83078ee8d1cSJulian Grajkowski 		return EINVAL;
83178ee8d1cSJulian Grajkowski 	}
83278ee8d1cSJulian Grajkowski 	return 0;
83378ee8d1cSJulian Grajkowski }
83478ee8d1cSJulian Grajkowski 
83578ee8d1cSJulian Grajkowski static struct icp_qat_uof_strtable *
qat_uclo_map_str_table(struct icp_qat_uclo_objhdr * obj_hdr,char * tab_name,struct icp_qat_uof_strtable * str_table)83678ee8d1cSJulian Grajkowski qat_uclo_map_str_table(struct icp_qat_uclo_objhdr *obj_hdr,
83778ee8d1cSJulian Grajkowski 		       char *tab_name,
83878ee8d1cSJulian Grajkowski 		       struct icp_qat_uof_strtable *str_table)
83978ee8d1cSJulian Grajkowski {
84078ee8d1cSJulian Grajkowski 	struct icp_qat_uof_chunkhdr *chunk_hdr;
84178ee8d1cSJulian Grajkowski 
84278ee8d1cSJulian Grajkowski 	chunk_hdr =
84378ee8d1cSJulian Grajkowski 	    qat_uclo_find_chunk((struct icp_qat_uof_objhdr *)obj_hdr->file_buff,
84478ee8d1cSJulian Grajkowski 				tab_name,
84578ee8d1cSJulian Grajkowski 				NULL);
84678ee8d1cSJulian Grajkowski 	if (chunk_hdr) {
84778ee8d1cSJulian Grajkowski 		int hdr_size;
84878ee8d1cSJulian Grajkowski 
84978ee8d1cSJulian Grajkowski 		memcpy(&str_table->table_len,
85078ee8d1cSJulian Grajkowski 		       obj_hdr->file_buff + chunk_hdr->offset,
85178ee8d1cSJulian Grajkowski 		       sizeof(str_table->table_len));
85278ee8d1cSJulian Grajkowski 		hdr_size = (char *)&str_table->strings - (char *)str_table;
85378ee8d1cSJulian Grajkowski 		str_table->strings = (uintptr_t)obj_hdr->file_buff +
85478ee8d1cSJulian Grajkowski 		    chunk_hdr->offset + hdr_size;
85578ee8d1cSJulian Grajkowski 		return str_table;
85678ee8d1cSJulian Grajkowski 	}
85778ee8d1cSJulian Grajkowski 	return NULL;
85878ee8d1cSJulian Grajkowski }
85978ee8d1cSJulian Grajkowski 
86078ee8d1cSJulian Grajkowski static void
qat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj * encap_uof_obj,struct icp_qat_uclo_init_mem_table * init_mem_tab)86178ee8d1cSJulian Grajkowski qat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj *encap_uof_obj,
86278ee8d1cSJulian Grajkowski 			   struct icp_qat_uclo_init_mem_table *init_mem_tab)
86378ee8d1cSJulian Grajkowski {
86478ee8d1cSJulian Grajkowski 	struct icp_qat_uof_chunkhdr *chunk_hdr;
86578ee8d1cSJulian Grajkowski 
86678ee8d1cSJulian Grajkowski 	chunk_hdr =
86778ee8d1cSJulian Grajkowski 	    qat_uclo_find_chunk(encap_uof_obj->obj_hdr, ICP_QAT_UOF_IMEM, NULL);
86878ee8d1cSJulian Grajkowski 	if (chunk_hdr) {
86978ee8d1cSJulian Grajkowski 		memmove(&init_mem_tab->entry_num,
87078ee8d1cSJulian Grajkowski 			encap_uof_obj->beg_uof + chunk_hdr->offset,
87178ee8d1cSJulian Grajkowski 			sizeof(unsigned int));
87278ee8d1cSJulian Grajkowski 		init_mem_tab->init_mem =
87378ee8d1cSJulian Grajkowski 		    (struct icp_qat_uof_initmem *)(encap_uof_obj->beg_uof +
87478ee8d1cSJulian Grajkowski 						   chunk_hdr->offset +
87578ee8d1cSJulian Grajkowski 						   sizeof(unsigned int));
87678ee8d1cSJulian Grajkowski 	}
87778ee8d1cSJulian Grajkowski }
87878ee8d1cSJulian Grajkowski 
87978ee8d1cSJulian Grajkowski static unsigned int
qat_uclo_get_dev_type(struct icp_qat_fw_loader_handle * handle)88078ee8d1cSJulian Grajkowski qat_uclo_get_dev_type(struct icp_qat_fw_loader_handle *handle)
88178ee8d1cSJulian Grajkowski {
88278ee8d1cSJulian Grajkowski 	switch (pci_get_device(GET_DEV(handle->accel_dev))) {
88378ee8d1cSJulian Grajkowski 	case ADF_DH895XCC_PCI_DEVICE_ID:
88478ee8d1cSJulian Grajkowski 		return ICP_QAT_AC_895XCC_DEV_TYPE;
88578ee8d1cSJulian Grajkowski 	case ADF_C62X_PCI_DEVICE_ID:
88678ee8d1cSJulian Grajkowski 		return ICP_QAT_AC_C62X_DEV_TYPE;
88778ee8d1cSJulian Grajkowski 	case ADF_C3XXX_PCI_DEVICE_ID:
88878ee8d1cSJulian Grajkowski 		return ICP_QAT_AC_C3XXX_DEV_TYPE;
88978ee8d1cSJulian Grajkowski 	case ADF_200XX_PCI_DEVICE_ID:
89078ee8d1cSJulian Grajkowski 		return ICP_QAT_AC_200XX_DEV_TYPE;
89178ee8d1cSJulian Grajkowski 	case ADF_C4XXX_PCI_DEVICE_ID:
89278ee8d1cSJulian Grajkowski 		return ICP_QAT_AC_C4XXX_DEV_TYPE;
893a977168cSMichal Gulbicki 	case ADF_4XXX_PCI_DEVICE_ID:
894a977168cSMichal Gulbicki 	case ADF_401XX_PCI_DEVICE_ID:
895a977168cSMichal Gulbicki 		return ICP_QAT_AC_4XXX_A_DEV_TYPE;
89678ee8d1cSJulian Grajkowski 	default:
89778ee8d1cSJulian Grajkowski 		pr_err("QAT: unsupported device 0x%x\n",
89878ee8d1cSJulian Grajkowski 		       pci_get_device(GET_DEV(handle->accel_dev)));
89978ee8d1cSJulian Grajkowski 		return 0;
90078ee8d1cSJulian Grajkowski 	}
90178ee8d1cSJulian Grajkowski }
90278ee8d1cSJulian Grajkowski 
90378ee8d1cSJulian Grajkowski static int
qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle * obj_handle)90478ee8d1cSJulian Grajkowski qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle *obj_handle)
90578ee8d1cSJulian Grajkowski {
90678ee8d1cSJulian Grajkowski 	unsigned int maj_ver, prod_type = obj_handle->prod_type;
90778ee8d1cSJulian Grajkowski 
90878ee8d1cSJulian Grajkowski 	if (!(prod_type & obj_handle->encap_uof_obj.obj_hdr->ac_dev_type)) {
90978ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF type 0x%x doesn't match with platform 0x%x\n",
91078ee8d1cSJulian Grajkowski 		       obj_handle->encap_uof_obj.obj_hdr->ac_dev_type,
91178ee8d1cSJulian Grajkowski 		       prod_type);
91278ee8d1cSJulian Grajkowski 		return EINVAL;
91378ee8d1cSJulian Grajkowski 	}
91478ee8d1cSJulian Grajkowski 	maj_ver = obj_handle->prod_rev & 0xff;
91578ee8d1cSJulian Grajkowski 	if (obj_handle->encap_uof_obj.obj_hdr->max_cpu_ver < maj_ver ||
91678ee8d1cSJulian Grajkowski 	    obj_handle->encap_uof_obj.obj_hdr->min_cpu_ver > maj_ver) {
91778ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF maj_ver 0x%x out of range\n", maj_ver);
91878ee8d1cSJulian Grajkowski 		return EINVAL;
91978ee8d1cSJulian Grajkowski 	}
92078ee8d1cSJulian Grajkowski 	return 0;
92178ee8d1cSJulian Grajkowski }
92278ee8d1cSJulian Grajkowski 
92378ee8d1cSJulian Grajkowski static int
qat_uclo_init_reg(struct icp_qat_fw_loader_handle * handle,unsigned char ae,unsigned char ctx_mask,enum icp_qat_uof_regtype reg_type,unsigned short reg_addr,unsigned int value)92478ee8d1cSJulian Grajkowski qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle,
92578ee8d1cSJulian Grajkowski 		  unsigned char ae,
92678ee8d1cSJulian Grajkowski 		  unsigned char ctx_mask,
92778ee8d1cSJulian Grajkowski 		  enum icp_qat_uof_regtype reg_type,
92878ee8d1cSJulian Grajkowski 		  unsigned short reg_addr,
92978ee8d1cSJulian Grajkowski 		  unsigned int value)
93078ee8d1cSJulian Grajkowski {
93178ee8d1cSJulian Grajkowski 	switch (reg_type) {
93278ee8d1cSJulian Grajkowski 	case ICP_GPA_ABS:
93378ee8d1cSJulian Grajkowski 	case ICP_GPB_ABS:
93478ee8d1cSJulian Grajkowski 		ctx_mask = 0;
93578ee8d1cSJulian Grajkowski 		return qat_hal_init_gpr(
93678ee8d1cSJulian Grajkowski 		    handle, ae, ctx_mask, reg_type, reg_addr, value);
93778ee8d1cSJulian Grajkowski 	case ICP_GPA_REL:
93878ee8d1cSJulian Grajkowski 	case ICP_GPB_REL:
93978ee8d1cSJulian Grajkowski 		return qat_hal_init_gpr(
94078ee8d1cSJulian Grajkowski 		    handle, ae, ctx_mask, reg_type, reg_addr, value);
94178ee8d1cSJulian Grajkowski 	case ICP_SR_ABS:
94278ee8d1cSJulian Grajkowski 	case ICP_DR_ABS:
94378ee8d1cSJulian Grajkowski 	case ICP_SR_RD_ABS:
94478ee8d1cSJulian Grajkowski 	case ICP_DR_RD_ABS:
94578ee8d1cSJulian Grajkowski 		ctx_mask = 0;
94678ee8d1cSJulian Grajkowski 		return qat_hal_init_rd_xfer(
94778ee8d1cSJulian Grajkowski 		    handle, ae, ctx_mask, reg_type, reg_addr, value);
94878ee8d1cSJulian Grajkowski 	case ICP_SR_REL:
94978ee8d1cSJulian Grajkowski 	case ICP_DR_REL:
95078ee8d1cSJulian Grajkowski 	case ICP_SR_RD_REL:
95178ee8d1cSJulian Grajkowski 	case ICP_DR_RD_REL:
95278ee8d1cSJulian Grajkowski 		return qat_hal_init_rd_xfer(
95378ee8d1cSJulian Grajkowski 		    handle, ae, ctx_mask, reg_type, reg_addr, value);
95478ee8d1cSJulian Grajkowski 	case ICP_SR_WR_ABS:
95578ee8d1cSJulian Grajkowski 	case ICP_DR_WR_ABS:
95678ee8d1cSJulian Grajkowski 		ctx_mask = 0;
95778ee8d1cSJulian Grajkowski 		return qat_hal_init_wr_xfer(
95878ee8d1cSJulian Grajkowski 		    handle, ae, ctx_mask, reg_type, reg_addr, value);
95978ee8d1cSJulian Grajkowski 	case ICP_SR_WR_REL:
96078ee8d1cSJulian Grajkowski 	case ICP_DR_WR_REL:
96178ee8d1cSJulian Grajkowski 		return qat_hal_init_wr_xfer(
96278ee8d1cSJulian Grajkowski 		    handle, ae, ctx_mask, reg_type, reg_addr, value);
96378ee8d1cSJulian Grajkowski 	case ICP_NEIGH_REL:
96478ee8d1cSJulian Grajkowski 		return qat_hal_init_nn(handle, ae, ctx_mask, reg_addr, value);
96578ee8d1cSJulian Grajkowski 	default:
96678ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF uses unsupported reg type 0x%x\n", reg_type);
96778ee8d1cSJulian Grajkowski 		return EFAULT;
96878ee8d1cSJulian Grajkowski 	}
96978ee8d1cSJulian Grajkowski 	return 0;
97078ee8d1cSJulian Grajkowski }
97178ee8d1cSJulian Grajkowski 
97278ee8d1cSJulian Grajkowski static int
qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle * handle,unsigned int ae,struct icp_qat_uclo_encapme * encap_ae)97378ee8d1cSJulian Grajkowski qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle *handle,
97478ee8d1cSJulian Grajkowski 		      unsigned int ae,
97578ee8d1cSJulian Grajkowski 		      struct icp_qat_uclo_encapme *encap_ae)
97678ee8d1cSJulian Grajkowski {
97778ee8d1cSJulian Grajkowski 	unsigned int i;
97878ee8d1cSJulian Grajkowski 	unsigned char ctx_mask;
97978ee8d1cSJulian Grajkowski 	struct icp_qat_uof_init_regsym *init_regsym;
98078ee8d1cSJulian Grajkowski 
98178ee8d1cSJulian Grajkowski 	if (ICP_QAT_CTX_MODE(encap_ae->img_ptr->ae_mode) ==
98278ee8d1cSJulian Grajkowski 	    ICP_QAT_UCLO_MAX_CTX)
98378ee8d1cSJulian Grajkowski 		ctx_mask = 0xff;
98478ee8d1cSJulian Grajkowski 	else
98578ee8d1cSJulian Grajkowski 		ctx_mask = 0x55;
98678ee8d1cSJulian Grajkowski 
98778ee8d1cSJulian Grajkowski 	for (i = 0; i < encap_ae->init_regsym_num; i++) {
98878ee8d1cSJulian Grajkowski 		unsigned int exp_res;
98978ee8d1cSJulian Grajkowski 
99078ee8d1cSJulian Grajkowski 		init_regsym = &encap_ae->init_regsym[i];
99178ee8d1cSJulian Grajkowski 		exp_res = init_regsym->value;
99278ee8d1cSJulian Grajkowski 		switch (init_regsym->init_type) {
99378ee8d1cSJulian Grajkowski 		case ICP_QAT_UOF_INIT_REG:
99478ee8d1cSJulian Grajkowski 			qat_uclo_init_reg(handle,
99578ee8d1cSJulian Grajkowski 					  ae,
99678ee8d1cSJulian Grajkowski 					  ctx_mask,
99778ee8d1cSJulian Grajkowski 					  (enum icp_qat_uof_regtype)
99878ee8d1cSJulian Grajkowski 					      init_regsym->reg_type,
99978ee8d1cSJulian Grajkowski 					  (unsigned short)init_regsym->reg_addr,
100078ee8d1cSJulian Grajkowski 					  exp_res);
100178ee8d1cSJulian Grajkowski 			break;
100278ee8d1cSJulian Grajkowski 		case ICP_QAT_UOF_INIT_REG_CTX:
100378ee8d1cSJulian Grajkowski 			/* check if ctx is appropriate for the ctxMode */
100478ee8d1cSJulian Grajkowski 			if (!((1 << init_regsym->ctx) & ctx_mask)) {
100578ee8d1cSJulian Grajkowski 				pr_err("QAT: invalid ctx num = 0x%x\n",
100678ee8d1cSJulian Grajkowski 				       init_regsym->ctx);
100778ee8d1cSJulian Grajkowski 				return EINVAL;
100878ee8d1cSJulian Grajkowski 			}
100978ee8d1cSJulian Grajkowski 			qat_uclo_init_reg(
101078ee8d1cSJulian Grajkowski 			    handle,
101178ee8d1cSJulian Grajkowski 			    ae,
101278ee8d1cSJulian Grajkowski 			    (unsigned char)(1 << init_regsym->ctx),
101378ee8d1cSJulian Grajkowski 			    (enum icp_qat_uof_regtype)init_regsym->reg_type,
101478ee8d1cSJulian Grajkowski 			    (unsigned short)init_regsym->reg_addr,
101578ee8d1cSJulian Grajkowski 			    exp_res);
101678ee8d1cSJulian Grajkowski 			break;
101778ee8d1cSJulian Grajkowski 		case ICP_QAT_UOF_INIT_EXPR:
101878ee8d1cSJulian Grajkowski 			pr_err("QAT: INIT_EXPR feature not supported\n");
101978ee8d1cSJulian Grajkowski 			return EINVAL;
102078ee8d1cSJulian Grajkowski 		case ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP:
102178ee8d1cSJulian Grajkowski 			pr_err("QAT: INIT_EXPR_ENDIAN_SWAP not supported\n");
102278ee8d1cSJulian Grajkowski 			return EINVAL;
102378ee8d1cSJulian Grajkowski 		default:
102478ee8d1cSJulian Grajkowski 			break;
102578ee8d1cSJulian Grajkowski 		}
102678ee8d1cSJulian Grajkowski 	}
102778ee8d1cSJulian Grajkowski 	return 0;
102878ee8d1cSJulian Grajkowski }
102978ee8d1cSJulian Grajkowski 
103078ee8d1cSJulian Grajkowski static int
qat_uclo_init_globals(struct icp_qat_fw_loader_handle * handle)103178ee8d1cSJulian Grajkowski qat_uclo_init_globals(struct icp_qat_fw_loader_handle *handle)
103278ee8d1cSJulian Grajkowski {
103378ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
103478ee8d1cSJulian Grajkowski 	unsigned int s;
103578ee8d1cSJulian Grajkowski 	unsigned int ae = 0;
103678ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_aedata *aed;
103778ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
103878ee8d1cSJulian Grajkowski 
103978ee8d1cSJulian Grajkowski 	if (obj_handle->global_inited)
104078ee8d1cSJulian Grajkowski 		return 0;
104178ee8d1cSJulian Grajkowski 	if (obj_handle->init_mem_tab.entry_num) {
104278ee8d1cSJulian Grajkowski 		if (qat_uclo_init_memory(handle)) {
104378ee8d1cSJulian Grajkowski 			pr_err("QAT: initialize memory failed\n");
104478ee8d1cSJulian Grajkowski 			return EINVAL;
104578ee8d1cSJulian Grajkowski 		}
104678ee8d1cSJulian Grajkowski 	}
104778ee8d1cSJulian Grajkowski 
104878ee8d1cSJulian Grajkowski 	for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num)
104978ee8d1cSJulian Grajkowski 	{
105078ee8d1cSJulian Grajkowski 		aed = &obj_handle->ae_data[ae];
105178ee8d1cSJulian Grajkowski 		for (s = 0; s < aed->slice_num; s++) {
105278ee8d1cSJulian Grajkowski 			if (!aed->ae_slices[s].encap_image)
105378ee8d1cSJulian Grajkowski 				continue;
105478ee8d1cSJulian Grajkowski 			if (qat_uclo_init_reg_sym(
105578ee8d1cSJulian Grajkowski 				handle, ae, aed->ae_slices[s].encap_image))
105678ee8d1cSJulian Grajkowski 				return EINVAL;
105778ee8d1cSJulian Grajkowski 		}
105878ee8d1cSJulian Grajkowski 	}
105978ee8d1cSJulian Grajkowski 	obj_handle->global_inited = 1;
106078ee8d1cSJulian Grajkowski 	return 0;
106178ee8d1cSJulian Grajkowski }
106278ee8d1cSJulian Grajkowski 
106378ee8d1cSJulian Grajkowski static int
qat_hal_set_modes(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uclo_objhandle * obj_handle,unsigned char ae,struct icp_qat_uof_image * uof_image)106478ee8d1cSJulian Grajkowski qat_hal_set_modes(struct icp_qat_fw_loader_handle *handle,
106578ee8d1cSJulian Grajkowski 		  struct icp_qat_uclo_objhandle *obj_handle,
106678ee8d1cSJulian Grajkowski 		  unsigned char ae,
106778ee8d1cSJulian Grajkowski 		  struct icp_qat_uof_image *uof_image)
106878ee8d1cSJulian Grajkowski {
106978ee8d1cSJulian Grajkowski 	unsigned char nn_mode;
107078ee8d1cSJulian Grajkowski 	char ae_mode = 0;
107178ee8d1cSJulian Grajkowski 
107278ee8d1cSJulian Grajkowski 	ae_mode = (char)ICP_QAT_CTX_MODE(uof_image->ae_mode);
107378ee8d1cSJulian Grajkowski 	if (qat_hal_set_ae_ctx_mode(handle, ae, ae_mode)) {
107478ee8d1cSJulian Grajkowski 		pr_err("QAT: qat_hal_set_ae_ctx_mode error\n");
107578ee8d1cSJulian Grajkowski 		return EFAULT;
107678ee8d1cSJulian Grajkowski 	}
107778ee8d1cSJulian Grajkowski 
107878ee8d1cSJulian Grajkowski 	ae_mode = (char)ICP_QAT_SHARED_USTORE_MODE(uof_image->ae_mode);
107978ee8d1cSJulian Grajkowski 	qat_hal_set_ae_scs_mode(handle, ae, ae_mode);
1080a977168cSMichal Gulbicki 	if (!IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
108178ee8d1cSJulian Grajkowski 		nn_mode = ICP_QAT_NN_MODE(uof_image->ae_mode);
108278ee8d1cSJulian Grajkowski 
108378ee8d1cSJulian Grajkowski 		if (qat_hal_set_ae_nn_mode(handle, ae, nn_mode)) {
108478ee8d1cSJulian Grajkowski 			pr_err("QAT: qat_hal_set_ae_nn_mode error\n");
108578ee8d1cSJulian Grajkowski 			return EFAULT;
108678ee8d1cSJulian Grajkowski 		}
1087a977168cSMichal Gulbicki 	}
108878ee8d1cSJulian Grajkowski 	ae_mode = (char)ICP_QAT_LOC_MEM0_MODE(uof_image->ae_mode);
108978ee8d1cSJulian Grajkowski 	if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM0, ae_mode)) {
109078ee8d1cSJulian Grajkowski 		pr_err("QAT: qat_hal_set_ae_lm_mode LMEM0 error\n");
109178ee8d1cSJulian Grajkowski 		return EFAULT;
109278ee8d1cSJulian Grajkowski 	}
109378ee8d1cSJulian Grajkowski 	ae_mode = (char)ICP_QAT_LOC_MEM1_MODE(uof_image->ae_mode);
109478ee8d1cSJulian Grajkowski 	if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM1, ae_mode)) {
109578ee8d1cSJulian Grajkowski 		pr_err("QAT: qat_hal_set_ae_lm_mode LMEM1 error\n");
109678ee8d1cSJulian Grajkowski 		return EFAULT;
109778ee8d1cSJulian Grajkowski 	}
1098a977168cSMichal Gulbicki 	if (IS_QAT_GEN3_OR_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
109978ee8d1cSJulian Grajkowski 		ae_mode = (char)ICP_QAT_LOC_MEM2_MODE(uof_image->ae_mode);
110078ee8d1cSJulian Grajkowski 		if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM2, ae_mode)) {
110178ee8d1cSJulian Grajkowski 			pr_err("QAT: qat_hal_set_ae_lm_mode LMEM2 error\n");
110278ee8d1cSJulian Grajkowski 			return EFAULT;
110378ee8d1cSJulian Grajkowski 		}
110478ee8d1cSJulian Grajkowski 		ae_mode = (char)ICP_QAT_LOC_MEM3_MODE(uof_image->ae_mode);
110578ee8d1cSJulian Grajkowski 		if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM3, ae_mode)) {
110678ee8d1cSJulian Grajkowski 			pr_err("QAT: qat_hal_set_ae_lm_mode LMEM3 error\n");
110778ee8d1cSJulian Grajkowski 			return EFAULT;
110878ee8d1cSJulian Grajkowski 		}
110978ee8d1cSJulian Grajkowski 		ae_mode = (char)ICP_QAT_LOC_TINDEX_MODE(uof_image->ae_mode);
111078ee8d1cSJulian Grajkowski 		qat_hal_set_ae_tindex_mode(handle, ae, ae_mode);
111178ee8d1cSJulian Grajkowski 	}
111278ee8d1cSJulian Grajkowski 	return 0;
111378ee8d1cSJulian Grajkowski }
111478ee8d1cSJulian Grajkowski 
111578ee8d1cSJulian Grajkowski static int
qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle * handle)111678ee8d1cSJulian Grajkowski qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle *handle)
111778ee8d1cSJulian Grajkowski {
111878ee8d1cSJulian Grajkowski 	int error;
111978ee8d1cSJulian Grajkowski 	unsigned char s;
112078ee8d1cSJulian Grajkowski 	unsigned char ae = 0;
112178ee8d1cSJulian Grajkowski 	struct icp_qat_uof_image *uof_image;
112278ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_aedata *ae_data;
112378ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
112478ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
112578ee8d1cSJulian Grajkowski 
112678ee8d1cSJulian Grajkowski 	for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num)
112778ee8d1cSJulian Grajkowski 	{
112878ee8d1cSJulian Grajkowski 		unsigned long cfg_ae_mask = handle->cfg_ae_mask;
112978ee8d1cSJulian Grajkowski 
113078ee8d1cSJulian Grajkowski 		if (!test_bit(ae, &cfg_ae_mask))
113178ee8d1cSJulian Grajkowski 			continue;
113278ee8d1cSJulian Grajkowski 
113378ee8d1cSJulian Grajkowski 		ae_data = &obj_handle->ae_data[ae];
113478ee8d1cSJulian Grajkowski 		for (s = 0; s < min_t(unsigned int,
113578ee8d1cSJulian Grajkowski 				      ae_data->slice_num,
113678ee8d1cSJulian Grajkowski 				      ICP_QAT_UCLO_MAX_CTX);
113778ee8d1cSJulian Grajkowski 		     s++) {
113878ee8d1cSJulian Grajkowski 			if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
113978ee8d1cSJulian Grajkowski 				continue;
114078ee8d1cSJulian Grajkowski 			uof_image = ae_data->ae_slices[s].encap_image->img_ptr;
114178ee8d1cSJulian Grajkowski 			error = qat_hal_set_modes(handle,
114278ee8d1cSJulian Grajkowski 						  obj_handle,
114378ee8d1cSJulian Grajkowski 						  ae,
114478ee8d1cSJulian Grajkowski 						  uof_image);
114578ee8d1cSJulian Grajkowski 			if (error)
114678ee8d1cSJulian Grajkowski 				return error;
114778ee8d1cSJulian Grajkowski 		}
114878ee8d1cSJulian Grajkowski 	}
114978ee8d1cSJulian Grajkowski 	return 0;
115078ee8d1cSJulian Grajkowski }
115178ee8d1cSJulian Grajkowski 
115278ee8d1cSJulian Grajkowski static void
qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle * handle)115378ee8d1cSJulian Grajkowski qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle *handle)
115478ee8d1cSJulian Grajkowski {
115578ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
115678ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_encapme *image;
115778ee8d1cSJulian Grajkowski 	int a;
115878ee8d1cSJulian Grajkowski 
115978ee8d1cSJulian Grajkowski 	for (a = 0; a < obj_handle->uimage_num; a++) {
116078ee8d1cSJulian Grajkowski 		image = &obj_handle->ae_uimage[a];
116178ee8d1cSJulian Grajkowski 		image->uwords_num =
116278ee8d1cSJulian Grajkowski 		    image->page->beg_addr_p + image->page->micro_words_num;
116378ee8d1cSJulian Grajkowski 	}
116478ee8d1cSJulian Grajkowski }
116578ee8d1cSJulian Grajkowski 
116678ee8d1cSJulian Grajkowski static int
qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle * handle)116778ee8d1cSJulian Grajkowski qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle *handle)
116878ee8d1cSJulian Grajkowski {
116978ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
117078ee8d1cSJulian Grajkowski 	unsigned int ae;
117178ee8d1cSJulian Grajkowski 
117278ee8d1cSJulian Grajkowski 	obj_handle->encap_uof_obj.beg_uof = obj_handle->obj_hdr->file_buff;
117378ee8d1cSJulian Grajkowski 	obj_handle->encap_uof_obj.obj_hdr =
117478ee8d1cSJulian Grajkowski 	    (struct icp_qat_uof_objhdr *)obj_handle->obj_hdr->file_buff;
117578ee8d1cSJulian Grajkowski 	obj_handle->uword_in_bytes = 6;
117678ee8d1cSJulian Grajkowski 	obj_handle->prod_type = qat_uclo_get_dev_type(handle);
117778ee8d1cSJulian Grajkowski 	obj_handle->prod_rev =
117878ee8d1cSJulian Grajkowski 	    PID_MAJOR_REV | (PID_MINOR_REV & handle->hal_handle->revision_id);
117978ee8d1cSJulian Grajkowski 	if (qat_uclo_check_uof_compat(obj_handle)) {
118078ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF incompatible\n");
118178ee8d1cSJulian Grajkowski 		return EINVAL;
118278ee8d1cSJulian Grajkowski 	}
118378ee8d1cSJulian Grajkowski 	obj_handle->uword_buf = malloc(UWORD_CPYBUF_SIZE * sizeof(uint64_t),
118478ee8d1cSJulian Grajkowski 				       M_QAT,
118578ee8d1cSJulian Grajkowski 				       M_WAITOK | M_ZERO);
118678ee8d1cSJulian Grajkowski 	obj_handle->ustore_phy_size =
118778ee8d1cSJulian Grajkowski 	    (obj_handle->prod_type == ICP_QAT_AC_C4XXX_DEV_TYPE) ? 0x2000 :
118878ee8d1cSJulian Grajkowski 								   0x4000;
118978ee8d1cSJulian Grajkowski 	if (!obj_handle->obj_hdr->file_buff ||
119078ee8d1cSJulian Grajkowski 	    !qat_uclo_map_str_table(obj_handle->obj_hdr,
119178ee8d1cSJulian Grajkowski 				    ICP_QAT_UOF_STRT,
119278ee8d1cSJulian Grajkowski 				    &obj_handle->str_table)) {
119378ee8d1cSJulian Grajkowski 		pr_err("QAT: UOF doesn't have effective images\n");
119478ee8d1cSJulian Grajkowski 		goto out_err;
119578ee8d1cSJulian Grajkowski 	}
119678ee8d1cSJulian Grajkowski 	obj_handle->uimage_num =
119778ee8d1cSJulian Grajkowski 	    qat_uclo_map_uimage(obj_handle,
119878ee8d1cSJulian Grajkowski 				obj_handle->ae_uimage,
119978ee8d1cSJulian Grajkowski 				ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX);
120078ee8d1cSJulian Grajkowski 	if (!obj_handle->uimage_num)
120178ee8d1cSJulian Grajkowski 		goto out_err;
120278ee8d1cSJulian Grajkowski 	if (qat_uclo_map_ae(handle, handle->hal_handle->ae_max_num)) {
120378ee8d1cSJulian Grajkowski 		pr_err("QAT: Bad object\n");
120478ee8d1cSJulian Grajkowski 		goto out_check_uof_aemask_err;
120578ee8d1cSJulian Grajkowski 	}
120678ee8d1cSJulian Grajkowski 	qat_uclo_init_uword_num(handle);
120778ee8d1cSJulian Grajkowski 	qat_uclo_map_initmem_table(&obj_handle->encap_uof_obj,
120878ee8d1cSJulian Grajkowski 				   &obj_handle->init_mem_tab);
120978ee8d1cSJulian Grajkowski 	if (qat_uclo_set_ae_mode(handle))
121078ee8d1cSJulian Grajkowski 		goto out_check_uof_aemask_err;
121178ee8d1cSJulian Grajkowski 	return 0;
121278ee8d1cSJulian Grajkowski out_check_uof_aemask_err:
121378ee8d1cSJulian Grajkowski 	for (ae = 0; ae < obj_handle->uimage_num; ae++)
121478ee8d1cSJulian Grajkowski 		free(obj_handle->ae_uimage[ae].page, M_QAT);
121578ee8d1cSJulian Grajkowski out_err:
121678ee8d1cSJulian Grajkowski 	free(obj_handle->uword_buf, M_QAT);
121778ee8d1cSJulian Grajkowski 	obj_handle->uword_buf = NULL;
121878ee8d1cSJulian Grajkowski 	return EFAULT;
121978ee8d1cSJulian Grajkowski }
122078ee8d1cSJulian Grajkowski 
122178ee8d1cSJulian Grajkowski static int
qat_uclo_map_suof_file_hdr(const struct icp_qat_fw_loader_handle * handle,const struct icp_qat_suof_filehdr * suof_ptr,int suof_size)122278ee8d1cSJulian Grajkowski qat_uclo_map_suof_file_hdr(const struct icp_qat_fw_loader_handle *handle,
122378ee8d1cSJulian Grajkowski 			   const struct icp_qat_suof_filehdr *suof_ptr,
122478ee8d1cSJulian Grajkowski 			   int suof_size)
122578ee8d1cSJulian Grajkowski {
122678ee8d1cSJulian Grajkowski 	unsigned int check_sum = 0;
122778ee8d1cSJulian Grajkowski 	unsigned int min_ver_offset = 0;
122878ee8d1cSJulian Grajkowski 	struct icp_qat_suof_handle *suof_handle = handle->sobj_handle;
122978ee8d1cSJulian Grajkowski 
123078ee8d1cSJulian Grajkowski 	suof_handle->file_id = ICP_QAT_SUOF_FID;
123178ee8d1cSJulian Grajkowski 	suof_handle->suof_buf = (const char *)suof_ptr;
123278ee8d1cSJulian Grajkowski 	suof_handle->suof_size = suof_size;
123378ee8d1cSJulian Grajkowski 	min_ver_offset =
123478ee8d1cSJulian Grajkowski 	    suof_size - offsetof(struct icp_qat_suof_filehdr, min_ver);
123578ee8d1cSJulian Grajkowski 	check_sum = qat_uclo_calc_str_checksum((const char *)&suof_ptr->min_ver,
123678ee8d1cSJulian Grajkowski 					       min_ver_offset);
123778ee8d1cSJulian Grajkowski 	if (check_sum != suof_ptr->check_sum) {
123878ee8d1cSJulian Grajkowski 		pr_err("QAT: incorrect SUOF checksum\n");
123978ee8d1cSJulian Grajkowski 		return EINVAL;
124078ee8d1cSJulian Grajkowski 	}
124178ee8d1cSJulian Grajkowski 	suof_handle->check_sum = suof_ptr->check_sum;
124278ee8d1cSJulian Grajkowski 	suof_handle->min_ver = suof_ptr->min_ver;
124378ee8d1cSJulian Grajkowski 	suof_handle->maj_ver = suof_ptr->maj_ver;
124478ee8d1cSJulian Grajkowski 	suof_handle->fw_type = suof_ptr->fw_type;
124578ee8d1cSJulian Grajkowski 	return 0;
124678ee8d1cSJulian Grajkowski }
124778ee8d1cSJulian Grajkowski 
124878ee8d1cSJulian Grajkowski static void
qat_uclo_map_simg(struct icp_qat_fw_loader_handle * handle,struct icp_qat_suof_img_hdr * suof_img_hdr,struct icp_qat_suof_chunk_hdr * suof_chunk_hdr)1249a977168cSMichal Gulbicki qat_uclo_map_simg(struct icp_qat_fw_loader_handle *handle,
125078ee8d1cSJulian Grajkowski 		  struct icp_qat_suof_img_hdr *suof_img_hdr,
125178ee8d1cSJulian Grajkowski 		  struct icp_qat_suof_chunk_hdr *suof_chunk_hdr)
125278ee8d1cSJulian Grajkowski {
1253a977168cSMichal Gulbicki 	struct icp_qat_suof_handle *suof_handle = handle->sobj_handle;
125478ee8d1cSJulian Grajkowski 	const struct icp_qat_simg_ae_mode *ae_mode;
125578ee8d1cSJulian Grajkowski 	struct icp_qat_suof_objhdr *suof_objhdr;
1256a977168cSMichal Gulbicki 	unsigned int device_id = pci_get_device(GET_DEV(handle->accel_dev));
125778ee8d1cSJulian Grajkowski 
125878ee8d1cSJulian Grajkowski 	suof_img_hdr->simg_buf =
125978ee8d1cSJulian Grajkowski 	    (suof_handle->suof_buf + suof_chunk_hdr->offset +
126078ee8d1cSJulian Grajkowski 	     sizeof(*suof_objhdr));
126178ee8d1cSJulian Grajkowski 	suof_img_hdr->simg_len =
126278ee8d1cSJulian Grajkowski 	    ((struct icp_qat_suof_objhdr *)(uintptr_t)(suof_handle->suof_buf +
126378ee8d1cSJulian Grajkowski 						       suof_chunk_hdr->offset))
126478ee8d1cSJulian Grajkowski 		->img_length;
126578ee8d1cSJulian Grajkowski 
126678ee8d1cSJulian Grajkowski 	suof_img_hdr->css_header = suof_img_hdr->simg_buf;
126778ee8d1cSJulian Grajkowski 	suof_img_hdr->css_key =
126878ee8d1cSJulian Grajkowski 	    (suof_img_hdr->css_header + sizeof(struct icp_qat_css_hdr));
126978ee8d1cSJulian Grajkowski 	suof_img_hdr->css_signature = suof_img_hdr->css_key +
1270a977168cSMichal Gulbicki 	    ICP_QAT_CSS_FWSK_MODULUS_LEN(device_id) +
1271a977168cSMichal Gulbicki 	    ICP_QAT_CSS_FWSK_EXPONENT_LEN(device_id);
127278ee8d1cSJulian Grajkowski 	suof_img_hdr->css_simg =
1273a977168cSMichal Gulbicki 	    suof_img_hdr->css_signature + ICP_QAT_CSS_SIGNATURE_LEN(device_id);
127478ee8d1cSJulian Grajkowski 
127578ee8d1cSJulian Grajkowski 	ae_mode = (const struct icp_qat_simg_ae_mode *)(suof_img_hdr->css_simg);
127678ee8d1cSJulian Grajkowski 	suof_img_hdr->ae_mask = ae_mode->ae_mask;
127778ee8d1cSJulian Grajkowski 	suof_img_hdr->simg_name = (unsigned long)&ae_mode->simg_name;
127878ee8d1cSJulian Grajkowski 	suof_img_hdr->appmeta_data = (unsigned long)&ae_mode->appmeta_data;
127978ee8d1cSJulian Grajkowski 	suof_img_hdr->fw_type = ae_mode->fw_type;
128078ee8d1cSJulian Grajkowski }
128178ee8d1cSJulian Grajkowski 
128278ee8d1cSJulian Grajkowski static void
qat_uclo_map_suof_symobjs(struct icp_qat_suof_handle * suof_handle,struct icp_qat_suof_chunk_hdr * suof_chunk_hdr)128378ee8d1cSJulian Grajkowski qat_uclo_map_suof_symobjs(struct icp_qat_suof_handle *suof_handle,
128478ee8d1cSJulian Grajkowski 			  struct icp_qat_suof_chunk_hdr *suof_chunk_hdr)
128578ee8d1cSJulian Grajkowski {
128678ee8d1cSJulian Grajkowski 	char **sym_str = (char **)&suof_handle->sym_str;
128778ee8d1cSJulian Grajkowski 	unsigned int *sym_size = &suof_handle->sym_size;
128878ee8d1cSJulian Grajkowski 	struct icp_qat_suof_strtable *str_table_obj;
128978ee8d1cSJulian Grajkowski 
129078ee8d1cSJulian Grajkowski 	*sym_size = *(unsigned int *)(uintptr_t)(suof_chunk_hdr->offset +
129178ee8d1cSJulian Grajkowski 						 suof_handle->suof_buf);
129278ee8d1cSJulian Grajkowski 	*sym_str =
129378ee8d1cSJulian Grajkowski 	    (char *)(uintptr_t)(suof_handle->suof_buf + suof_chunk_hdr->offset +
129478ee8d1cSJulian Grajkowski 				sizeof(str_table_obj->tab_length));
129578ee8d1cSJulian Grajkowski }
129678ee8d1cSJulian Grajkowski 
129778ee8d1cSJulian Grajkowski static int
qat_uclo_check_simg_compat(struct icp_qat_fw_loader_handle * handle,struct icp_qat_suof_img_hdr * img_hdr)129878ee8d1cSJulian Grajkowski qat_uclo_check_simg_compat(struct icp_qat_fw_loader_handle *handle,
129978ee8d1cSJulian Grajkowski 			   struct icp_qat_suof_img_hdr *img_hdr)
130078ee8d1cSJulian Grajkowski {
130178ee8d1cSJulian Grajkowski 	const struct icp_qat_simg_ae_mode *img_ae_mode = NULL;
130278ee8d1cSJulian Grajkowski 	unsigned int prod_rev, maj_ver, prod_type;
130378ee8d1cSJulian Grajkowski 
130478ee8d1cSJulian Grajkowski 	prod_type = qat_uclo_get_dev_type(handle);
130578ee8d1cSJulian Grajkowski 	img_ae_mode = (const struct icp_qat_simg_ae_mode *)img_hdr->css_simg;
130678ee8d1cSJulian Grajkowski 	prod_rev =
130778ee8d1cSJulian Grajkowski 	    PID_MAJOR_REV | (PID_MINOR_REV & handle->hal_handle->revision_id);
130878ee8d1cSJulian Grajkowski 	if (img_ae_mode->dev_type != prod_type) {
130978ee8d1cSJulian Grajkowski 		pr_err("QAT: incompatible product type %x\n",
131078ee8d1cSJulian Grajkowski 		       img_ae_mode->dev_type);
131178ee8d1cSJulian Grajkowski 		return EINVAL;
131278ee8d1cSJulian Grajkowski 	}
131378ee8d1cSJulian Grajkowski 	maj_ver = prod_rev & 0xff;
131478ee8d1cSJulian Grajkowski 	if (maj_ver > img_ae_mode->devmax_ver ||
131578ee8d1cSJulian Grajkowski 	    maj_ver < img_ae_mode->devmin_ver) {
131678ee8d1cSJulian Grajkowski 		pr_err("QAT: incompatible device maj_ver 0x%x\n", maj_ver);
131778ee8d1cSJulian Grajkowski 		return EINVAL;
131878ee8d1cSJulian Grajkowski 	}
131978ee8d1cSJulian Grajkowski 	return 0;
132078ee8d1cSJulian Grajkowski }
132178ee8d1cSJulian Grajkowski 
132278ee8d1cSJulian Grajkowski static void
qat_uclo_del_suof(struct icp_qat_fw_loader_handle * handle)132378ee8d1cSJulian Grajkowski qat_uclo_del_suof(struct icp_qat_fw_loader_handle *handle)
132478ee8d1cSJulian Grajkowski {
132578ee8d1cSJulian Grajkowski 	struct icp_qat_suof_handle *sobj_handle = handle->sobj_handle;
132678ee8d1cSJulian Grajkowski 
132778ee8d1cSJulian Grajkowski 	free(sobj_handle->img_table.simg_hdr, M_QAT);
132878ee8d1cSJulian Grajkowski 	sobj_handle->img_table.simg_hdr = NULL;
132978ee8d1cSJulian Grajkowski 	free(handle->sobj_handle, M_QAT);
133078ee8d1cSJulian Grajkowski 	handle->sobj_handle = NULL;
133178ee8d1cSJulian Grajkowski }
133278ee8d1cSJulian Grajkowski 
133378ee8d1cSJulian Grajkowski static void
qat_uclo_tail_img(struct icp_qat_suof_img_hdr * suof_img_hdr,unsigned int img_id,unsigned int num_simgs)133478ee8d1cSJulian Grajkowski qat_uclo_tail_img(struct icp_qat_suof_img_hdr *suof_img_hdr,
133578ee8d1cSJulian Grajkowski 		  unsigned int img_id,
133678ee8d1cSJulian Grajkowski 		  unsigned int num_simgs)
133778ee8d1cSJulian Grajkowski {
133878ee8d1cSJulian Grajkowski 	struct icp_qat_suof_img_hdr img_header;
133978ee8d1cSJulian Grajkowski 
134078ee8d1cSJulian Grajkowski 	if ((img_id != num_simgs - 1) && img_id != ICP_QAT_UCLO_MAX_AE) {
134178ee8d1cSJulian Grajkowski 		memcpy(&img_header,
134278ee8d1cSJulian Grajkowski 		       &suof_img_hdr[num_simgs - 1],
134378ee8d1cSJulian Grajkowski 		       sizeof(*suof_img_hdr));
134478ee8d1cSJulian Grajkowski 		memcpy(&suof_img_hdr[num_simgs - 1],
134578ee8d1cSJulian Grajkowski 		       &suof_img_hdr[img_id],
134678ee8d1cSJulian Grajkowski 		       sizeof(*suof_img_hdr));
134778ee8d1cSJulian Grajkowski 		memcpy(&suof_img_hdr[img_id],
134878ee8d1cSJulian Grajkowski 		       &img_header,
134978ee8d1cSJulian Grajkowski 		       sizeof(*suof_img_hdr));
135078ee8d1cSJulian Grajkowski 	}
135178ee8d1cSJulian Grajkowski }
135278ee8d1cSJulian Grajkowski 
135378ee8d1cSJulian Grajkowski static int
qat_uclo_map_suof(struct icp_qat_fw_loader_handle * handle,const struct icp_qat_suof_filehdr * suof_ptr,int suof_size)135478ee8d1cSJulian Grajkowski qat_uclo_map_suof(struct icp_qat_fw_loader_handle *handle,
135578ee8d1cSJulian Grajkowski 		  const struct icp_qat_suof_filehdr *suof_ptr,
135678ee8d1cSJulian Grajkowski 		  int suof_size)
135778ee8d1cSJulian Grajkowski {
135878ee8d1cSJulian Grajkowski 	struct icp_qat_suof_handle *suof_handle = handle->sobj_handle;
135978ee8d1cSJulian Grajkowski 	struct icp_qat_suof_chunk_hdr *suof_chunk_hdr = NULL;
136078ee8d1cSJulian Grajkowski 	struct icp_qat_suof_img_hdr *suof_img_hdr = NULL;
1361a977168cSMichal Gulbicki 	int ret = 0, ae0_img = ICP_QAT_UCLO_MAX_AE,
1362a977168cSMichal Gulbicki 	    aeMax_img = ICP_QAT_UCLO_MAX_AE;
136378ee8d1cSJulian Grajkowski 	unsigned int i = 0;
136478ee8d1cSJulian Grajkowski 	struct icp_qat_suof_img_hdr img_header;
136578ee8d1cSJulian Grajkowski 
136678ee8d1cSJulian Grajkowski 	if (!suof_ptr || suof_size == 0) {
136778ee8d1cSJulian Grajkowski 		pr_err("QAT: input parameter SUOF pointer/size is NULL\n");
136878ee8d1cSJulian Grajkowski 		return EINVAL;
136978ee8d1cSJulian Grajkowski 	}
137078ee8d1cSJulian Grajkowski 	if (qat_uclo_check_suof_format(suof_ptr))
137178ee8d1cSJulian Grajkowski 		return EINVAL;
137278ee8d1cSJulian Grajkowski 	ret = qat_uclo_map_suof_file_hdr(handle, suof_ptr, suof_size);
137378ee8d1cSJulian Grajkowski 	if (ret)
137478ee8d1cSJulian Grajkowski 		return ret;
137578ee8d1cSJulian Grajkowski 	suof_chunk_hdr = (struct icp_qat_suof_chunk_hdr *)((uintptr_t)suof_ptr +
137678ee8d1cSJulian Grajkowski 							   sizeof(*suof_ptr));
137778ee8d1cSJulian Grajkowski 
137878ee8d1cSJulian Grajkowski 	qat_uclo_map_suof_symobjs(suof_handle, suof_chunk_hdr);
137978ee8d1cSJulian Grajkowski 	suof_handle->img_table.num_simgs = suof_ptr->num_chunks - 1;
138078ee8d1cSJulian Grajkowski 
138178ee8d1cSJulian Grajkowski 	if (suof_handle->img_table.num_simgs != 0) {
138278ee8d1cSJulian Grajkowski 		suof_img_hdr = malloc(suof_handle->img_table.num_simgs *
138378ee8d1cSJulian Grajkowski 					  sizeof(img_header),
138478ee8d1cSJulian Grajkowski 				      M_QAT,
138578ee8d1cSJulian Grajkowski 				      M_WAITOK | M_ZERO);
138678ee8d1cSJulian Grajkowski 		suof_handle->img_table.simg_hdr = suof_img_hdr;
138778ee8d1cSJulian Grajkowski 	}
138878ee8d1cSJulian Grajkowski 
138978ee8d1cSJulian Grajkowski 	for (i = 0; i < suof_handle->img_table.num_simgs; i++) {
1390a977168cSMichal Gulbicki 		qat_uclo_map_simg(handle,
139178ee8d1cSJulian Grajkowski 				  &suof_img_hdr[i],
139278ee8d1cSJulian Grajkowski 				  &suof_chunk_hdr[1 + i]);
139378ee8d1cSJulian Grajkowski 		ret = qat_uclo_check_simg_compat(handle, &suof_img_hdr[i]);
139478ee8d1cSJulian Grajkowski 		if (ret)
139578ee8d1cSJulian Grajkowski 			return ret;
139678ee8d1cSJulian Grajkowski 		suof_img_hdr[i].ae_mask &= handle->cfg_ae_mask;
139778ee8d1cSJulian Grajkowski 		if ((suof_img_hdr[i].ae_mask & 0x1) != 0)
139878ee8d1cSJulian Grajkowski 			ae0_img = i;
139978ee8d1cSJulian Grajkowski 	}
1400a977168cSMichal Gulbicki 
1401a977168cSMichal Gulbicki 	if (!IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
140278ee8d1cSJulian Grajkowski 		qat_uclo_tail_img(suof_img_hdr,
140378ee8d1cSJulian Grajkowski 				  ae0_img,
140478ee8d1cSJulian Grajkowski 				  suof_handle->img_table.num_simgs);
1405a977168cSMichal Gulbicki 	} else {
1406a977168cSMichal Gulbicki 		if (suof_handle->img_table.num_simgs == 1)
1407a977168cSMichal Gulbicki 			return 0;
1408a977168cSMichal Gulbicki 		qat_uclo_tail_img(suof_img_hdr,
1409a977168cSMichal Gulbicki 				  ae0_img,
1410a977168cSMichal Gulbicki 				  suof_handle->img_table.num_simgs - 1);
1411a977168cSMichal Gulbicki 		for (i = 0; i < suof_handle->img_table.num_simgs; i++) {
1412a977168cSMichal Gulbicki 			if ((suof_img_hdr[i].ae_mask &
1413a977168cSMichal Gulbicki 			     (0x1 << (handle->hal_handle->ae_max_num - 1))) !=
1414a977168cSMichal Gulbicki 			    0) {
1415a977168cSMichal Gulbicki 				aeMax_img = i;
1416a977168cSMichal Gulbicki 				break;
1417a977168cSMichal Gulbicki 			}
1418a977168cSMichal Gulbicki 		}
1419a977168cSMichal Gulbicki 		qat_uclo_tail_img(suof_img_hdr,
1420a977168cSMichal Gulbicki 				  aeMax_img,
1421a977168cSMichal Gulbicki 				  suof_handle->img_table.num_simgs);
1422a977168cSMichal Gulbicki 	}
142378ee8d1cSJulian Grajkowski 	return 0;
142478ee8d1cSJulian Grajkowski }
142578ee8d1cSJulian Grajkowski 
142678ee8d1cSJulian Grajkowski #define ADD_ADDR(high, low) ((((uint64_t)high) << 32) + (low))
142778ee8d1cSJulian Grajkowski #define BITS_IN_DWORD 32
142878ee8d1cSJulian Grajkowski 
142978ee8d1cSJulian Grajkowski static int
qat_uclo_auth_fw(struct icp_qat_fw_loader_handle * handle,struct icp_qat_fw_auth_desc * desc)143078ee8d1cSJulian Grajkowski qat_uclo_auth_fw(struct icp_qat_fw_loader_handle *handle,
143178ee8d1cSJulian Grajkowski 		 struct icp_qat_fw_auth_desc *desc)
143278ee8d1cSJulian Grajkowski {
143378ee8d1cSJulian Grajkowski 	unsigned int fcu_sts, mem_cfg_err, retry = 0;
143478ee8d1cSJulian Grajkowski 	unsigned int fcu_ctl_csr, fcu_sts_csr;
143578ee8d1cSJulian Grajkowski 	unsigned int fcu_dram_hi_csr, fcu_dram_lo_csr;
143678ee8d1cSJulian Grajkowski 	u64 bus_addr;
143778ee8d1cSJulian Grajkowski 
143878ee8d1cSJulian Grajkowski 	bus_addr = ADD_ADDR(desc->css_hdr_high, desc->css_hdr_low) -
143978ee8d1cSJulian Grajkowski 	    sizeof(struct icp_qat_auth_chunk);
1440a977168cSMichal Gulbicki 	if (IS_QAT_GEN3_OR_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
144178ee8d1cSJulian Grajkowski 		fcu_ctl_csr = FCU_CONTROL_C4XXX;
144278ee8d1cSJulian Grajkowski 		fcu_sts_csr = FCU_STATUS_C4XXX;
144378ee8d1cSJulian Grajkowski 		fcu_dram_hi_csr = FCU_DRAM_ADDR_HI_C4XXX;
144478ee8d1cSJulian Grajkowski 		fcu_dram_lo_csr = FCU_DRAM_ADDR_LO_C4XXX;
144578ee8d1cSJulian Grajkowski 	} else {
144678ee8d1cSJulian Grajkowski 		fcu_ctl_csr = FCU_CONTROL;
144778ee8d1cSJulian Grajkowski 		fcu_sts_csr = FCU_STATUS;
144878ee8d1cSJulian Grajkowski 		fcu_dram_hi_csr = FCU_DRAM_ADDR_HI;
144978ee8d1cSJulian Grajkowski 		fcu_dram_lo_csr = FCU_DRAM_ADDR_LO;
145078ee8d1cSJulian Grajkowski 	}
145178ee8d1cSJulian Grajkowski 	SET_FCU_CSR(handle, fcu_dram_hi_csr, (bus_addr >> BITS_IN_DWORD));
145278ee8d1cSJulian Grajkowski 	SET_FCU_CSR(handle, fcu_dram_lo_csr, bus_addr);
145378ee8d1cSJulian Grajkowski 	SET_FCU_CSR(handle, fcu_ctl_csr, FCU_CTRL_CMD_AUTH);
145478ee8d1cSJulian Grajkowski 
145578ee8d1cSJulian Grajkowski 	do {
145678ee8d1cSJulian Grajkowski 		pause_ms("adfstop", FW_AUTH_WAIT_PERIOD);
145778ee8d1cSJulian Grajkowski 		fcu_sts = GET_FCU_CSR(handle, fcu_sts_csr);
145878ee8d1cSJulian Grajkowski 		if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_FAIL)
145978ee8d1cSJulian Grajkowski 			goto auth_fail;
146078ee8d1cSJulian Grajkowski 		if (((fcu_sts >> FCU_STS_AUTHFWLD_POS) & 0x1))
146178ee8d1cSJulian Grajkowski 			if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_DONE)
146278ee8d1cSJulian Grajkowski 				return 0;
146378ee8d1cSJulian Grajkowski 	} while (retry++ < FW_AUTH_MAX_RETRY);
146478ee8d1cSJulian Grajkowski auth_fail:
146578ee8d1cSJulian Grajkowski 	pr_err("QAT: authentication error (FCU_STATUS = 0x%x),retry = %d\n",
146678ee8d1cSJulian Grajkowski 	       fcu_sts & FCU_AUTH_STS_MASK,
146778ee8d1cSJulian Grajkowski 	       retry);
146878ee8d1cSJulian Grajkowski 	if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) {
146978ee8d1cSJulian Grajkowski 		mem_cfg_err =
147078ee8d1cSJulian Grajkowski 		    (GET_FCU_CSR(handle, FCU_STATUS1_C4XXX) & MEM_CFG_ERR_BIT);
147178ee8d1cSJulian Grajkowski 		if (mem_cfg_err)
147278ee8d1cSJulian Grajkowski 			pr_err("QAT: MEM_CFG_ERR\n");
147378ee8d1cSJulian Grajkowski 	}
147478ee8d1cSJulian Grajkowski 	return EINVAL;
147578ee8d1cSJulian Grajkowski }
147678ee8d1cSJulian Grajkowski 
147778ee8d1cSJulian Grajkowski static int
qat_uclo_is_broadcast(struct icp_qat_fw_loader_handle * handle,int imgid)1478a977168cSMichal Gulbicki qat_uclo_is_broadcast(struct icp_qat_fw_loader_handle *handle, int imgid)
1479a977168cSMichal Gulbicki {
1480a977168cSMichal Gulbicki 	struct icp_qat_suof_handle *sobj_handle;
1481a977168cSMichal Gulbicki 
1482a977168cSMichal Gulbicki 	if (!IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev))))
1483a977168cSMichal Gulbicki 		return 0;
1484a977168cSMichal Gulbicki 
1485a977168cSMichal Gulbicki 	sobj_handle = (struct icp_qat_suof_handle *)handle->sobj_handle;
1486a977168cSMichal Gulbicki 	if (handle->hal_handle->admin_ae_mask &
1487a977168cSMichal Gulbicki 	    sobj_handle->img_table.simg_hdr[imgid].ae_mask)
1488a977168cSMichal Gulbicki 		return 0;
1489a977168cSMichal Gulbicki 
1490a977168cSMichal Gulbicki 	return 1;
1491a977168cSMichal Gulbicki }
1492a977168cSMichal Gulbicki 
1493a977168cSMichal Gulbicki static int
qat_uclo_broadcast_load_fw(struct icp_qat_fw_loader_handle * handle,struct icp_qat_fw_auth_desc * desc)1494a977168cSMichal Gulbicki qat_uclo_broadcast_load_fw(struct icp_qat_fw_loader_handle *handle,
1495a977168cSMichal Gulbicki 			   struct icp_qat_fw_auth_desc *desc)
1496a977168cSMichal Gulbicki {
1497a977168cSMichal Gulbicki 	unsigned int i = 0;
1498a977168cSMichal Gulbicki 	unsigned int fcuSts = 0, fcuAeBroadcastMask = 0;
1499a977168cSMichal Gulbicki 	unsigned int retry = 0;
1500a977168cSMichal Gulbicki 	unsigned int fcuStsCsr = 0;
1501a977168cSMichal Gulbicki 	unsigned int fcuCtlCsr = 0;
1502a977168cSMichal Gulbicki 	unsigned int loadedAes = 0;
1503a977168cSMichal Gulbicki 	unsigned int device_id = pci_get_device(GET_DEV(handle->accel_dev));
1504a977168cSMichal Gulbicki 
1505a977168cSMichal Gulbicki 	if (IS_QAT_GEN4(device_id)) {
1506a977168cSMichal Gulbicki 		fcuCtlCsr = FCU_CONTROL_4XXX;
1507a977168cSMichal Gulbicki 		fcuStsCsr = FCU_STATUS_4XXX;
1508a977168cSMichal Gulbicki 	} else {
1509a977168cSMichal Gulbicki 		pr_err("Uclo_BroadcastLoadFW only applicable for CPM20\n");
1510a977168cSMichal Gulbicki 		return EINVAL;
1511a977168cSMichal Gulbicki 	}
1512a977168cSMichal Gulbicki 
1513a977168cSMichal Gulbicki 	for (i = 0; i < ICP_QAT_UCLO_MAX_AE; i++) {
1514a977168cSMichal Gulbicki 		if (!test_bit(i, (unsigned long *)&handle->hal_handle->ae_mask))
1515a977168cSMichal Gulbicki 			continue;
1516a977168cSMichal Gulbicki 
1517a977168cSMichal Gulbicki 		if (qat_hal_check_ae_active(handle, (unsigned char)i)) {
1518a977168cSMichal Gulbicki 			pr_err(
1519a977168cSMichal Gulbicki 			    "Uclo_BroadcastLoadFW error (invalid AE status)\n");
1520a977168cSMichal Gulbicki 			return EINVAL;
1521a977168cSMichal Gulbicki 		}
1522a977168cSMichal Gulbicki 
1523a977168cSMichal Gulbicki 		if ((desc->ae_mask >> i) & 0x1) {
1524a977168cSMichal Gulbicki 			fcuAeBroadcastMask |= 1 << i;
1525a977168cSMichal Gulbicki 		}
1526a977168cSMichal Gulbicki 	}
1527a977168cSMichal Gulbicki 
1528a977168cSMichal Gulbicki 	if (fcuAeBroadcastMask) {
1529a977168cSMichal Gulbicki 		retry = 0;
1530a977168cSMichal Gulbicki 		SET_FCU_CSR(handle,
1531a977168cSMichal Gulbicki 			    FCU_ME_BROADCAST_MASK_TYPE,
1532a977168cSMichal Gulbicki 			    fcuAeBroadcastMask);
1533a977168cSMichal Gulbicki 		SET_FCU_CSR(handle, fcuCtlCsr, FCU_CTRL_CMD_LOAD);
1534a977168cSMichal Gulbicki 		do {
1535a977168cSMichal Gulbicki 			msleep(FW_AUTH_WAIT_PERIOD);
1536a977168cSMichal Gulbicki 			fcuSts = GET_FCU_CSR(handle, fcuStsCsr);
1537a977168cSMichal Gulbicki 
1538a977168cSMichal Gulbicki 			if ((fcuSts & FCU_AUTH_STS_MASK) == FCU_STS_LOAD_FAIL) {
1539a977168cSMichal Gulbicki 				pr_err(
1540a977168cSMichal Gulbicki 				    "Uclo_BroadcastLoadFW fail (fcu_status = 0x%x)\n",
1541a977168cSMichal Gulbicki 				    fcuSts & FCU_AUTH_STS_MASK);
1542a977168cSMichal Gulbicki 				return EINVAL;
1543a977168cSMichal Gulbicki 			} else if ((fcuSts & FCU_AUTH_STS_MASK) ==
1544a977168cSMichal Gulbicki 				   FCU_STS_LOAD_DONE) {
1545a977168cSMichal Gulbicki 				if (IS_QAT_GEN4(device_id))
1546a977168cSMichal Gulbicki 					loadedAes =
1547a977168cSMichal Gulbicki 					    GET_FCU_CSR(handle,
1548a977168cSMichal Gulbicki 							FCU_AE_LOADED_4XXX);
1549a977168cSMichal Gulbicki 				else
1550a977168cSMichal Gulbicki 					loadedAes =
1551a977168cSMichal Gulbicki 					    (fcuSts >> FCU_LOADED_AE_POS);
1552a977168cSMichal Gulbicki 
1553a977168cSMichal Gulbicki 				if ((loadedAes & fcuAeBroadcastMask) ==
1554a977168cSMichal Gulbicki 				    fcuAeBroadcastMask)
1555a977168cSMichal Gulbicki 					break;
1556a977168cSMichal Gulbicki 			} else if ((fcuSts & FCU_AUTH_STS_MASK) ==
1557a977168cSMichal Gulbicki 				   FCU_STS_VERI_DONE) {
1558a977168cSMichal Gulbicki 				SET_FCU_CSR(handle,
1559a977168cSMichal Gulbicki 					    fcuCtlCsr,
1560a977168cSMichal Gulbicki 					    FCU_CTRL_CMD_LOAD);
1561a977168cSMichal Gulbicki 			}
1562a977168cSMichal Gulbicki 		} while (retry++ < FW_BROADCAST_MAX_RETRY);
1563a977168cSMichal Gulbicki 		if (retry > FW_BROADCAST_MAX_RETRY) {
1564a977168cSMichal Gulbicki 			pr_err(
1565a977168cSMichal Gulbicki 			    "Uclo_BroadcastLoadFW fail(fcu_status = 0x%x),retry = %d\n",
1566a977168cSMichal Gulbicki 			    fcuSts & FCU_AUTH_STS_MASK,
1567a977168cSMichal Gulbicki 			    retry);
1568a977168cSMichal Gulbicki 			return EINVAL;
1569a977168cSMichal Gulbicki 		}
1570a977168cSMichal Gulbicki 	}
1571a977168cSMichal Gulbicki 	return 0;
1572a977168cSMichal Gulbicki }
1573a977168cSMichal Gulbicki 
1574a977168cSMichal Gulbicki static int
qat_uclo_simg_alloc(struct icp_qat_fw_loader_handle * handle,struct icp_firml_dram_desc * dram_desc,unsigned int size)157578ee8d1cSJulian Grajkowski qat_uclo_simg_alloc(struct icp_qat_fw_loader_handle *handle,
157678ee8d1cSJulian Grajkowski 		    struct icp_firml_dram_desc *dram_desc,
157778ee8d1cSJulian Grajkowski 		    unsigned int size)
157878ee8d1cSJulian Grajkowski {
157978ee8d1cSJulian Grajkowski 	int ret;
158078ee8d1cSJulian Grajkowski 
158178ee8d1cSJulian Grajkowski 	ret = bus_dma_mem_create(&dram_desc->dram_mem,
158278ee8d1cSJulian Grajkowski 				 handle->accel_dev->dma_tag,
158378ee8d1cSJulian Grajkowski 				 1,
158478ee8d1cSJulian Grajkowski 				 BUS_SPACE_MAXADDR,
158578ee8d1cSJulian Grajkowski 				 size,
158678ee8d1cSJulian Grajkowski 				 0);
158778ee8d1cSJulian Grajkowski 	if (ret != 0)
158878ee8d1cSJulian Grajkowski 		return ret;
158978ee8d1cSJulian Grajkowski 	dram_desc->dram_base_addr_v = dram_desc->dram_mem.dma_vaddr;
159078ee8d1cSJulian Grajkowski 	dram_desc->dram_bus_addr = dram_desc->dram_mem.dma_baddr;
159178ee8d1cSJulian Grajkowski 	dram_desc->dram_size = size;
159278ee8d1cSJulian Grajkowski 	return 0;
159378ee8d1cSJulian Grajkowski }
159478ee8d1cSJulian Grajkowski 
159578ee8d1cSJulian Grajkowski static void
qat_uclo_simg_free(struct icp_qat_fw_loader_handle * handle,struct icp_firml_dram_desc * dram_desc)159678ee8d1cSJulian Grajkowski qat_uclo_simg_free(struct icp_qat_fw_loader_handle *handle,
159778ee8d1cSJulian Grajkowski 		   struct icp_firml_dram_desc *dram_desc)
159878ee8d1cSJulian Grajkowski {
159978ee8d1cSJulian Grajkowski 	if (handle && dram_desc && dram_desc->dram_base_addr_v)
160078ee8d1cSJulian Grajkowski 		bus_dma_mem_free(&dram_desc->dram_mem);
160178ee8d1cSJulian Grajkowski 
160278ee8d1cSJulian Grajkowski 	if (dram_desc)
160378ee8d1cSJulian Grajkowski 		explicit_bzero(dram_desc, sizeof(*dram_desc));
160478ee8d1cSJulian Grajkowski }
160578ee8d1cSJulian Grajkowski 
160678ee8d1cSJulian Grajkowski static int
qat_uclo_map_auth_fw(struct icp_qat_fw_loader_handle * handle,const char * image,unsigned int size,struct icp_firml_dram_desc * img_desc,struct icp_qat_fw_auth_desc ** desc)160778ee8d1cSJulian Grajkowski qat_uclo_map_auth_fw(struct icp_qat_fw_loader_handle *handle,
160878ee8d1cSJulian Grajkowski 		     const char *image,
160978ee8d1cSJulian Grajkowski 		     unsigned int size,
161078ee8d1cSJulian Grajkowski 		     struct icp_firml_dram_desc *img_desc,
161178ee8d1cSJulian Grajkowski 		     struct icp_qat_fw_auth_desc **desc)
161278ee8d1cSJulian Grajkowski {
161378ee8d1cSJulian Grajkowski 	const struct icp_qat_css_hdr *css_hdr =
161478ee8d1cSJulian Grajkowski 	    (const struct icp_qat_css_hdr *)image;
161578ee8d1cSJulian Grajkowski 	struct icp_qat_fw_auth_desc *auth_desc;
161678ee8d1cSJulian Grajkowski 	struct icp_qat_auth_chunk *auth_chunk;
161778ee8d1cSJulian Grajkowski 	u64 virt_addr, bus_addr, virt_base;
161878ee8d1cSJulian Grajkowski 	unsigned int length, simg_offset = sizeof(*auth_chunk);
1619a977168cSMichal Gulbicki 	unsigned int device_id = pci_get_device(GET_DEV(handle->accel_dev));
162078ee8d1cSJulian Grajkowski 
1621a977168cSMichal Gulbicki 	if (size >
1622a977168cSMichal Gulbicki 	    (ICP_QAT_AE_IMG_OFFSET(device_id) + ICP_QAT_CSS_MAX_IMAGE_LEN)) {
162378ee8d1cSJulian Grajkowski 		pr_err("QAT: error, input image size overflow %d\n", size);
162478ee8d1cSJulian Grajkowski 		return EINVAL;
162578ee8d1cSJulian Grajkowski 	}
162678ee8d1cSJulian Grajkowski 	length = (css_hdr->fw_type == CSS_AE_FIRMWARE) ?
1627a977168cSMichal Gulbicki 	    ICP_QAT_CSS_AE_SIMG_LEN(device_id) + simg_offset :
1628a977168cSMichal Gulbicki 	    size + ICP_QAT_CSS_FWSK_PAD_LEN(device_id) + simg_offset;
162978ee8d1cSJulian Grajkowski 	if (qat_uclo_simg_alloc(handle, img_desc, length)) {
163078ee8d1cSJulian Grajkowski 		pr_err("QAT: error, allocate continuous dram fail\n");
163178ee8d1cSJulian Grajkowski 		return -ENOMEM;
163278ee8d1cSJulian Grajkowski 	}
163378ee8d1cSJulian Grajkowski 
163478ee8d1cSJulian Grajkowski 	auth_chunk = img_desc->dram_base_addr_v;
163578ee8d1cSJulian Grajkowski 	auth_chunk->chunk_size = img_desc->dram_size;
163678ee8d1cSJulian Grajkowski 	auth_chunk->chunk_bus_addr = img_desc->dram_bus_addr;
163778ee8d1cSJulian Grajkowski 	virt_base = (uintptr_t)img_desc->dram_base_addr_v + simg_offset;
163878ee8d1cSJulian Grajkowski 	bus_addr = img_desc->dram_bus_addr + simg_offset;
163978ee8d1cSJulian Grajkowski 	auth_desc = img_desc->dram_base_addr_v;
164078ee8d1cSJulian Grajkowski 	auth_desc->css_hdr_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
164178ee8d1cSJulian Grajkowski 	auth_desc->css_hdr_low = (unsigned int)bus_addr;
164278ee8d1cSJulian Grajkowski 	virt_addr = virt_base;
164378ee8d1cSJulian Grajkowski 
164478ee8d1cSJulian Grajkowski 	memcpy((void *)(uintptr_t)virt_addr, image, sizeof(*css_hdr));
164578ee8d1cSJulian Grajkowski 	/* pub key */
164678ee8d1cSJulian Grajkowski 	bus_addr = ADD_ADDR(auth_desc->css_hdr_high, auth_desc->css_hdr_low) +
164778ee8d1cSJulian Grajkowski 	    sizeof(*css_hdr);
164878ee8d1cSJulian Grajkowski 	virt_addr = virt_addr + sizeof(*css_hdr);
164978ee8d1cSJulian Grajkowski 
165078ee8d1cSJulian Grajkowski 	auth_desc->fwsk_pub_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
165178ee8d1cSJulian Grajkowski 	auth_desc->fwsk_pub_low = (unsigned int)bus_addr;
165278ee8d1cSJulian Grajkowski 
165378ee8d1cSJulian Grajkowski 	memcpy((void *)(uintptr_t)virt_addr,
165478ee8d1cSJulian Grajkowski 	       (const void *)(image + sizeof(*css_hdr)),
1655a977168cSMichal Gulbicki 	       ICP_QAT_CSS_FWSK_MODULUS_LEN(device_id));
165678ee8d1cSJulian Grajkowski 	/* padding */
1657a977168cSMichal Gulbicki 	explicit_bzero((void *)(uintptr_t)(
1658a977168cSMichal Gulbicki 			   virt_addr + ICP_QAT_CSS_FWSK_MODULUS_LEN(device_id)),
1659a977168cSMichal Gulbicki 		       ICP_QAT_CSS_FWSK_PAD_LEN(device_id));
166078ee8d1cSJulian Grajkowski 
166178ee8d1cSJulian Grajkowski 	/* exponent */
1662a977168cSMichal Gulbicki 	memcpy((void *)(uintptr_t)(virt_addr +
1663a977168cSMichal Gulbicki 				   ICP_QAT_CSS_FWSK_MODULUS_LEN(device_id) +
1664a977168cSMichal Gulbicki 				   ICP_QAT_CSS_FWSK_PAD_LEN(device_id)),
166578ee8d1cSJulian Grajkowski 	       (const void *)(image + sizeof(*css_hdr) +
1666a977168cSMichal Gulbicki 			      ICP_QAT_CSS_FWSK_MODULUS_LEN(device_id)),
166778ee8d1cSJulian Grajkowski 	       sizeof(unsigned int));
166878ee8d1cSJulian Grajkowski 
166978ee8d1cSJulian Grajkowski 	/* signature */
167078ee8d1cSJulian Grajkowski 	bus_addr = ADD_ADDR(auth_desc->fwsk_pub_high, auth_desc->fwsk_pub_low) +
1671a977168cSMichal Gulbicki 	    ICP_QAT_CSS_FWSK_PUB_LEN(device_id);
1672a977168cSMichal Gulbicki 	virt_addr = virt_addr + ICP_QAT_CSS_FWSK_PUB_LEN(device_id);
167378ee8d1cSJulian Grajkowski 	auth_desc->signature_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
167478ee8d1cSJulian Grajkowski 	auth_desc->signature_low = (unsigned int)bus_addr;
167578ee8d1cSJulian Grajkowski 
167678ee8d1cSJulian Grajkowski 	memcpy((void *)(uintptr_t)virt_addr,
167778ee8d1cSJulian Grajkowski 	       (const void *)(image + sizeof(*css_hdr) +
1678a977168cSMichal Gulbicki 			      ICP_QAT_CSS_FWSK_MODULUS_LEN(device_id) +
1679a977168cSMichal Gulbicki 			      ICP_QAT_CSS_FWSK_EXPONENT_LEN(device_id)),
1680a977168cSMichal Gulbicki 	       ICP_QAT_CSS_SIGNATURE_LEN(device_id));
168178ee8d1cSJulian Grajkowski 
168278ee8d1cSJulian Grajkowski 	bus_addr =
168378ee8d1cSJulian Grajkowski 	    ADD_ADDR(auth_desc->signature_high, auth_desc->signature_low) +
1684a977168cSMichal Gulbicki 	    ICP_QAT_CSS_SIGNATURE_LEN(device_id);
1685a977168cSMichal Gulbicki 	virt_addr += ICP_QAT_CSS_SIGNATURE_LEN(device_id);
168678ee8d1cSJulian Grajkowski 
168778ee8d1cSJulian Grajkowski 	auth_desc->img_high = (unsigned int)(bus_addr >> BITS_IN_DWORD);
168878ee8d1cSJulian Grajkowski 	auth_desc->img_low = (unsigned int)bus_addr;
1689a977168cSMichal Gulbicki 	auth_desc->img_len = size - ICP_QAT_AE_IMG_OFFSET(device_id);
169078ee8d1cSJulian Grajkowski 	memcpy((void *)(uintptr_t)virt_addr,
1691a977168cSMichal Gulbicki 	       (const void *)(image + ICP_QAT_AE_IMG_OFFSET(device_id)),
169278ee8d1cSJulian Grajkowski 	       auth_desc->img_len);
169378ee8d1cSJulian Grajkowski 	virt_addr = virt_base;
169478ee8d1cSJulian Grajkowski 	/* AE firmware */
169578ee8d1cSJulian Grajkowski 	if (((struct icp_qat_css_hdr *)(uintptr_t)virt_addr)->fw_type ==
169678ee8d1cSJulian Grajkowski 	    CSS_AE_FIRMWARE) {
169778ee8d1cSJulian Grajkowski 		auth_desc->img_ae_mode_data_high = auth_desc->img_high;
169878ee8d1cSJulian Grajkowski 		auth_desc->img_ae_mode_data_low = auth_desc->img_low;
169978ee8d1cSJulian Grajkowski 		bus_addr = ADD_ADDR(auth_desc->img_ae_mode_data_high,
170078ee8d1cSJulian Grajkowski 				    auth_desc->img_ae_mode_data_low) +
170178ee8d1cSJulian Grajkowski 		    sizeof(struct icp_qat_simg_ae_mode);
170278ee8d1cSJulian Grajkowski 
170378ee8d1cSJulian Grajkowski 		auth_desc->img_ae_init_data_high =
170478ee8d1cSJulian Grajkowski 		    (unsigned int)(bus_addr >> BITS_IN_DWORD);
170578ee8d1cSJulian Grajkowski 		auth_desc->img_ae_init_data_low = (unsigned int)bus_addr;
170678ee8d1cSJulian Grajkowski 		bus_addr += ICP_QAT_SIMG_AE_INIT_SEQ_LEN;
170778ee8d1cSJulian Grajkowski 		auth_desc->img_ae_insts_high =
170878ee8d1cSJulian Grajkowski 		    (unsigned int)(bus_addr >> BITS_IN_DWORD);
170978ee8d1cSJulian Grajkowski 		auth_desc->img_ae_insts_low = (unsigned int)bus_addr;
171078ee8d1cSJulian Grajkowski 		virt_addr += sizeof(struct icp_qat_css_hdr) +
1711a977168cSMichal Gulbicki 		    ICP_QAT_CSS_FWSK_PUB_LEN(device_id) +
1712a977168cSMichal Gulbicki 		    ICP_QAT_CSS_SIGNATURE_LEN(device_id);
171378ee8d1cSJulian Grajkowski 		auth_desc->ae_mask =
171478ee8d1cSJulian Grajkowski 		    ((struct icp_qat_simg_ae_mode *)virt_addr)->ae_mask &
171578ee8d1cSJulian Grajkowski 		    handle->cfg_ae_mask;
171678ee8d1cSJulian Grajkowski 	} else {
171778ee8d1cSJulian Grajkowski 		auth_desc->img_ae_insts_high = auth_desc->img_high;
171878ee8d1cSJulian Grajkowski 		auth_desc->img_ae_insts_low = auth_desc->img_low;
171978ee8d1cSJulian Grajkowski 	}
172078ee8d1cSJulian Grajkowski 	*desc = auth_desc;
172178ee8d1cSJulian Grajkowski 	return 0;
172278ee8d1cSJulian Grajkowski }
172378ee8d1cSJulian Grajkowski 
172478ee8d1cSJulian Grajkowski static int
qat_uclo_load_fw(struct icp_qat_fw_loader_handle * handle,struct icp_qat_fw_auth_desc * desc)172578ee8d1cSJulian Grajkowski qat_uclo_load_fw(struct icp_qat_fw_loader_handle *handle,
172678ee8d1cSJulian Grajkowski 		 struct icp_qat_fw_auth_desc *desc)
172778ee8d1cSJulian Grajkowski {
172878ee8d1cSJulian Grajkowski 	unsigned int i = 0;
172978ee8d1cSJulian Grajkowski 	unsigned int fcu_sts;
173078ee8d1cSJulian Grajkowski 	unsigned int fcu_sts_csr, fcu_ctl_csr;
173178ee8d1cSJulian Grajkowski 	unsigned int loaded_aes = FCU_LOADED_AE_POS;
173278ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
173378ee8d1cSJulian Grajkowski 
1734a977168cSMichal Gulbicki 	if (IS_QAT_GEN3_OR_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
173578ee8d1cSJulian Grajkowski 		fcu_ctl_csr = FCU_CONTROL_C4XXX;
173678ee8d1cSJulian Grajkowski 		fcu_sts_csr = FCU_STATUS_C4XXX;
173778ee8d1cSJulian Grajkowski 
173878ee8d1cSJulian Grajkowski 	} else {
173978ee8d1cSJulian Grajkowski 		fcu_ctl_csr = FCU_CONTROL;
174078ee8d1cSJulian Grajkowski 		fcu_sts_csr = FCU_STATUS;
174178ee8d1cSJulian Grajkowski 	}
174278ee8d1cSJulian Grajkowski 
174378ee8d1cSJulian Grajkowski 	for_each_set_bit(i, &ae_mask, handle->hal_handle->ae_max_num)
174478ee8d1cSJulian Grajkowski 	{
174578ee8d1cSJulian Grajkowski 		int retry = 0;
174678ee8d1cSJulian Grajkowski 
174778ee8d1cSJulian Grajkowski 		if (!((desc->ae_mask >> i) & 0x1))
174878ee8d1cSJulian Grajkowski 			continue;
174978ee8d1cSJulian Grajkowski 		if (qat_hal_check_ae_active(handle, i)) {
175078ee8d1cSJulian Grajkowski 			pr_err("QAT: AE %d is active\n", i);
175178ee8d1cSJulian Grajkowski 			return EINVAL;
175278ee8d1cSJulian Grajkowski 		}
175378ee8d1cSJulian Grajkowski 		SET_FCU_CSR(handle,
175478ee8d1cSJulian Grajkowski 			    fcu_ctl_csr,
1755a977168cSMichal Gulbicki 			    (FCU_CTRL_CMD_LOAD |
1756a977168cSMichal Gulbicki 			     (IS_QAT_GEN4(
1757a977168cSMichal Gulbicki 				  pci_get_device(GET_DEV(handle->accel_dev))) ?
1758a977168cSMichal Gulbicki 				  (1 << FCU_CTRL_BROADCAST_POS) :
1759a977168cSMichal Gulbicki 				  0) |
1760a977168cSMichal Gulbicki 			     (i << FCU_CTRL_AE_POS)));
176178ee8d1cSJulian Grajkowski 
176278ee8d1cSJulian Grajkowski 		do {
176378ee8d1cSJulian Grajkowski 			pause_ms("adfstop", FW_AUTH_WAIT_PERIOD);
176478ee8d1cSJulian Grajkowski 			fcu_sts = GET_FCU_CSR(handle, fcu_sts_csr);
176578ee8d1cSJulian Grajkowski 			if ((fcu_sts & FCU_AUTH_STS_MASK) ==
176678ee8d1cSJulian Grajkowski 			    FCU_STS_LOAD_DONE) {
1767a977168cSMichal Gulbicki 				loaded_aes = IS_QAT_GEN3_OR_GEN4(pci_get_device(
176878ee8d1cSJulian Grajkowski 						 GET_DEV(handle->accel_dev))) ?
176978ee8d1cSJulian Grajkowski 				    GET_FCU_CSR(handle, FCU_AE_LOADED_C4XXX) :
177078ee8d1cSJulian Grajkowski 				    (fcu_sts >> FCU_LOADED_AE_POS);
177178ee8d1cSJulian Grajkowski 				if (loaded_aes & (1 << i))
177278ee8d1cSJulian Grajkowski 					break;
177378ee8d1cSJulian Grajkowski 			}
177478ee8d1cSJulian Grajkowski 		} while (retry++ < FW_AUTH_MAX_RETRY);
177578ee8d1cSJulian Grajkowski 		if (retry > FW_AUTH_MAX_RETRY) {
177678ee8d1cSJulian Grajkowski 			pr_err("QAT: firmware load failed timeout %x\n", retry);
177778ee8d1cSJulian Grajkowski 			return EINVAL;
177878ee8d1cSJulian Grajkowski 		}
177978ee8d1cSJulian Grajkowski 	}
178078ee8d1cSJulian Grajkowski 	return 0;
178178ee8d1cSJulian Grajkowski }
178278ee8d1cSJulian Grajkowski 
178378ee8d1cSJulian Grajkowski static int
qat_uclo_map_suof_obj(struct icp_qat_fw_loader_handle * handle,const void * addr_ptr,int mem_size)178478ee8d1cSJulian Grajkowski qat_uclo_map_suof_obj(struct icp_qat_fw_loader_handle *handle,
178578ee8d1cSJulian Grajkowski 		      const void *addr_ptr,
178678ee8d1cSJulian Grajkowski 		      int mem_size)
178778ee8d1cSJulian Grajkowski {
178878ee8d1cSJulian Grajkowski 	struct icp_qat_suof_handle *suof_handle;
178978ee8d1cSJulian Grajkowski 
179078ee8d1cSJulian Grajkowski 	suof_handle = malloc(sizeof(*suof_handle), M_QAT, M_WAITOK | M_ZERO);
179178ee8d1cSJulian Grajkowski 	handle->sobj_handle = suof_handle;
179278ee8d1cSJulian Grajkowski 	if (qat_uclo_map_suof(handle, addr_ptr, mem_size)) {
179378ee8d1cSJulian Grajkowski 		qat_uclo_del_suof(handle);
179478ee8d1cSJulian Grajkowski 		pr_err("QAT: map SUOF failed\n");
179578ee8d1cSJulian Grajkowski 		return EINVAL;
179678ee8d1cSJulian Grajkowski 	}
179778ee8d1cSJulian Grajkowski 	return 0;
179878ee8d1cSJulian Grajkowski }
179978ee8d1cSJulian Grajkowski 
180078ee8d1cSJulian Grajkowski int
qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle * handle,const void * addr_ptr,int mem_size)180178ee8d1cSJulian Grajkowski qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle,
180278ee8d1cSJulian Grajkowski 		   const void *addr_ptr,
180378ee8d1cSJulian Grajkowski 		   int mem_size)
180478ee8d1cSJulian Grajkowski {
180578ee8d1cSJulian Grajkowski 	struct icp_qat_fw_auth_desc *desc = NULL;
180678ee8d1cSJulian Grajkowski 	struct icp_firml_dram_desc img_desc;
180778ee8d1cSJulian Grajkowski 	int status = 0;
180878ee8d1cSJulian Grajkowski 
180978ee8d1cSJulian Grajkowski 	if (handle->fw_auth) {
181078ee8d1cSJulian Grajkowski 		status = qat_uclo_map_auth_fw(
181178ee8d1cSJulian Grajkowski 		    handle, addr_ptr, mem_size, &img_desc, &desc);
181278ee8d1cSJulian Grajkowski 		if (!status)
181378ee8d1cSJulian Grajkowski 			status = qat_uclo_auth_fw(handle, desc);
181478ee8d1cSJulian Grajkowski 
181578ee8d1cSJulian Grajkowski 		qat_uclo_simg_free(handle, &img_desc);
181678ee8d1cSJulian Grajkowski 	} else {
1817a977168cSMichal Gulbicki 		if (IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev)))) {
1818a977168cSMichal Gulbicki 			device_printf(
1819a977168cSMichal Gulbicki 			    NULL, "QAT: PKE service is not allowed because ");
1820a977168cSMichal Gulbicki 			device_printf(NULL, "MMP fw will not be loaded for ");
1821a977168cSMichal Gulbicki 			device_printf(NULL,
1822a977168cSMichal Gulbicki 				      "device 0x%x",
1823a977168cSMichal Gulbicki 				      pci_get_device(
1824a977168cSMichal Gulbicki 					  GET_DEV(handle->accel_dev)));
1825a977168cSMichal Gulbicki 			return status;
1826a977168cSMichal Gulbicki 		}
182778ee8d1cSJulian Grajkowski 		if (pci_get_device(GET_DEV(handle->accel_dev)) ==
182878ee8d1cSJulian Grajkowski 		    ADF_C3XXX_PCI_DEVICE_ID) {
182978ee8d1cSJulian Grajkowski 			pr_err("QAT: C3XXX doesn't support unsigned MMP\n");
183078ee8d1cSJulian Grajkowski 			return EINVAL;
183178ee8d1cSJulian Grajkowski 		}
183278ee8d1cSJulian Grajkowski 		status = qat_uclo_wr_sram_by_words(handle,
183378ee8d1cSJulian Grajkowski 						   handle->hal_sram_offset,
183478ee8d1cSJulian Grajkowski 						   addr_ptr,
183578ee8d1cSJulian Grajkowski 						   mem_size);
183678ee8d1cSJulian Grajkowski 	}
183778ee8d1cSJulian Grajkowski 	return status;
183878ee8d1cSJulian Grajkowski }
183978ee8d1cSJulian Grajkowski 
184078ee8d1cSJulian Grajkowski static int
qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle * handle,const void * addr_ptr,int mem_size)184178ee8d1cSJulian Grajkowski qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
184278ee8d1cSJulian Grajkowski 		     const void *addr_ptr,
184378ee8d1cSJulian Grajkowski 		     int mem_size)
184478ee8d1cSJulian Grajkowski {
184578ee8d1cSJulian Grajkowski 	struct icp_qat_uof_filehdr *filehdr;
184678ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *objhdl;
184778ee8d1cSJulian Grajkowski 
184878ee8d1cSJulian Grajkowski 	objhdl = malloc(sizeof(*objhdl), M_QAT, M_WAITOK | M_ZERO);
184978ee8d1cSJulian Grajkowski 	objhdl->obj_buf = malloc(mem_size, M_QAT, M_WAITOK);
185078ee8d1cSJulian Grajkowski 	bcopy(addr_ptr, objhdl->obj_buf, mem_size);
185178ee8d1cSJulian Grajkowski 	filehdr = (struct icp_qat_uof_filehdr *)objhdl->obj_buf;
185278ee8d1cSJulian Grajkowski 	if (qat_uclo_check_uof_format(filehdr))
185378ee8d1cSJulian Grajkowski 		goto out_objhdr_err;
185478ee8d1cSJulian Grajkowski 	objhdl->obj_hdr = qat_uclo_map_chunk((char *)objhdl->obj_buf,
185578ee8d1cSJulian Grajkowski 					     filehdr,
185678ee8d1cSJulian Grajkowski 					     ICP_QAT_UOF_OBJS);
185778ee8d1cSJulian Grajkowski 	if (!objhdl->obj_hdr) {
185878ee8d1cSJulian Grajkowski 		pr_err("QAT: object file chunk is null\n");
185978ee8d1cSJulian Grajkowski 		goto out_objhdr_err;
186078ee8d1cSJulian Grajkowski 	}
186178ee8d1cSJulian Grajkowski 	handle->obj_handle = objhdl;
186278ee8d1cSJulian Grajkowski 	if (qat_uclo_parse_uof_obj(handle))
186378ee8d1cSJulian Grajkowski 		goto out_overlay_obj_err;
186478ee8d1cSJulian Grajkowski 	return 0;
186578ee8d1cSJulian Grajkowski 
186678ee8d1cSJulian Grajkowski out_overlay_obj_err:
186778ee8d1cSJulian Grajkowski 	handle->obj_handle = NULL;
186878ee8d1cSJulian Grajkowski 	free(objhdl->obj_hdr, M_QAT);
186978ee8d1cSJulian Grajkowski out_objhdr_err:
187078ee8d1cSJulian Grajkowski 	free(objhdl->obj_buf, M_QAT);
187178ee8d1cSJulian Grajkowski 	free(objhdl, M_QAT);
187278ee8d1cSJulian Grajkowski 	return ENOMEM;
187378ee8d1cSJulian Grajkowski }
187478ee8d1cSJulian Grajkowski 
187578ee8d1cSJulian Grajkowski static int
qat_uclo_map_mof_file_hdr(struct icp_qat_fw_loader_handle * handle,const struct icp_qat_mof_file_hdr * mof_ptr,u32 mof_size)187678ee8d1cSJulian Grajkowski qat_uclo_map_mof_file_hdr(struct icp_qat_fw_loader_handle *handle,
187778ee8d1cSJulian Grajkowski 			  const struct icp_qat_mof_file_hdr *mof_ptr,
187878ee8d1cSJulian Grajkowski 			  u32 mof_size)
187978ee8d1cSJulian Grajkowski {
188078ee8d1cSJulian Grajkowski 	unsigned int checksum = 0;
188178ee8d1cSJulian Grajkowski 	unsigned int min_ver_offset = 0;
188278ee8d1cSJulian Grajkowski 	struct icp_qat_mof_handle *mobj_handle = handle->mobj_handle;
188378ee8d1cSJulian Grajkowski 
188478ee8d1cSJulian Grajkowski 	mobj_handle->file_id = ICP_QAT_MOF_FID;
188578ee8d1cSJulian Grajkowski 	mobj_handle->mof_buf = (const char *)mof_ptr;
188678ee8d1cSJulian Grajkowski 	mobj_handle->mof_size = mof_size;
188778ee8d1cSJulian Grajkowski 
188878ee8d1cSJulian Grajkowski 	min_ver_offset =
188978ee8d1cSJulian Grajkowski 	    mof_size - offsetof(struct icp_qat_mof_file_hdr, min_ver);
189078ee8d1cSJulian Grajkowski 	checksum = qat_uclo_calc_str_checksum((const char *)&mof_ptr->min_ver,
189178ee8d1cSJulian Grajkowski 					      min_ver_offset);
189278ee8d1cSJulian Grajkowski 	if (checksum != mof_ptr->checksum) {
189378ee8d1cSJulian Grajkowski 		pr_err("QAT: incorrect MOF checksum\n");
189478ee8d1cSJulian Grajkowski 		return EINVAL;
189578ee8d1cSJulian Grajkowski 	}
189678ee8d1cSJulian Grajkowski 	mobj_handle->checksum = mof_ptr->checksum;
189778ee8d1cSJulian Grajkowski 	mobj_handle->min_ver = mof_ptr->min_ver;
189878ee8d1cSJulian Grajkowski 	mobj_handle->maj_ver = mof_ptr->maj_ver;
189978ee8d1cSJulian Grajkowski 	return 0;
190078ee8d1cSJulian Grajkowski }
190178ee8d1cSJulian Grajkowski 
190278ee8d1cSJulian Grajkowski void
qat_uclo_del_mof(struct icp_qat_fw_loader_handle * handle)190378ee8d1cSJulian Grajkowski qat_uclo_del_mof(struct icp_qat_fw_loader_handle *handle)
190478ee8d1cSJulian Grajkowski {
190578ee8d1cSJulian Grajkowski 	struct icp_qat_mof_handle *mobj_handle = handle->mobj_handle;
190678ee8d1cSJulian Grajkowski 
190778ee8d1cSJulian Grajkowski 	free(mobj_handle->obj_table.obj_hdr, M_QAT);
190878ee8d1cSJulian Grajkowski 	mobj_handle->obj_table.obj_hdr = NULL;
190978ee8d1cSJulian Grajkowski 	free(handle->mobj_handle, M_QAT);
191078ee8d1cSJulian Grajkowski 	handle->mobj_handle = NULL;
191178ee8d1cSJulian Grajkowski }
191278ee8d1cSJulian Grajkowski 
191378ee8d1cSJulian Grajkowski static int
qat_uclo_seek_obj_inside_mof(struct icp_qat_mof_handle * mobj_handle,const char * obj_name,const char ** obj_ptr,unsigned int * obj_size)191478ee8d1cSJulian Grajkowski qat_uclo_seek_obj_inside_mof(struct icp_qat_mof_handle *mobj_handle,
191578ee8d1cSJulian Grajkowski 			     const char *obj_name,
191678ee8d1cSJulian Grajkowski 			     const char **obj_ptr,
191778ee8d1cSJulian Grajkowski 			     unsigned int *obj_size)
191878ee8d1cSJulian Grajkowski {
191978ee8d1cSJulian Grajkowski 	unsigned int i;
192078ee8d1cSJulian Grajkowski 	struct icp_qat_mof_objhdr *obj_hdr = mobj_handle->obj_table.obj_hdr;
192178ee8d1cSJulian Grajkowski 
192278ee8d1cSJulian Grajkowski 	for (i = 0; i < mobj_handle->obj_table.num_objs; i++) {
192378ee8d1cSJulian Grajkowski 		if (!strncmp(obj_hdr[i].obj_name,
192478ee8d1cSJulian Grajkowski 			     obj_name,
192578ee8d1cSJulian Grajkowski 			     ICP_QAT_SUOF_OBJ_NAME_LEN)) {
192678ee8d1cSJulian Grajkowski 			*obj_ptr = obj_hdr[i].obj_buf;
192778ee8d1cSJulian Grajkowski 			*obj_size = obj_hdr[i].obj_size;
192878ee8d1cSJulian Grajkowski 			break;
192978ee8d1cSJulian Grajkowski 		}
193078ee8d1cSJulian Grajkowski 	}
193178ee8d1cSJulian Grajkowski 
193278ee8d1cSJulian Grajkowski 	if (i >= mobj_handle->obj_table.num_objs) {
193378ee8d1cSJulian Grajkowski 		pr_err("QAT: object %s is not found inside MOF\n", obj_name);
193478ee8d1cSJulian Grajkowski 		return EFAULT;
193578ee8d1cSJulian Grajkowski 	}
193678ee8d1cSJulian Grajkowski 	return 0;
193778ee8d1cSJulian Grajkowski }
193878ee8d1cSJulian Grajkowski 
193978ee8d1cSJulian Grajkowski static int
qat_uclo_map_obj_from_mof(struct icp_qat_mof_handle * mobj_handle,struct icp_qat_mof_objhdr * mobj_hdr,struct icp_qat_mof_obj_chunkhdr * obj_chunkhdr)194078ee8d1cSJulian Grajkowski qat_uclo_map_obj_from_mof(struct icp_qat_mof_handle *mobj_handle,
194178ee8d1cSJulian Grajkowski 			  struct icp_qat_mof_objhdr *mobj_hdr,
194278ee8d1cSJulian Grajkowski 			  struct icp_qat_mof_obj_chunkhdr *obj_chunkhdr)
194378ee8d1cSJulian Grajkowski {
194478ee8d1cSJulian Grajkowski 	if ((strncmp((char *)obj_chunkhdr->chunk_id,
194578ee8d1cSJulian Grajkowski 		     ICP_QAT_UOF_IMAG,
194678ee8d1cSJulian Grajkowski 		     ICP_QAT_MOF_OBJ_CHUNKID_LEN)) == 0) {
194778ee8d1cSJulian Grajkowski 		mobj_hdr->obj_buf =
194878ee8d1cSJulian Grajkowski 		    (const char *)((unsigned long)obj_chunkhdr->offset +
194978ee8d1cSJulian Grajkowski 				   mobj_handle->uobjs_hdr);
195078ee8d1cSJulian Grajkowski 	} else if ((strncmp((char *)(obj_chunkhdr->chunk_id),
195178ee8d1cSJulian Grajkowski 			    ICP_QAT_SUOF_IMAG,
195278ee8d1cSJulian Grajkowski 			    ICP_QAT_MOF_OBJ_CHUNKID_LEN)) == 0) {
195378ee8d1cSJulian Grajkowski 		mobj_hdr->obj_buf =
195478ee8d1cSJulian Grajkowski 		    (const char *)((unsigned long)obj_chunkhdr->offset +
195578ee8d1cSJulian Grajkowski 				   mobj_handle->sobjs_hdr);
195678ee8d1cSJulian Grajkowski 
195778ee8d1cSJulian Grajkowski 	} else {
195878ee8d1cSJulian Grajkowski 		pr_err("QAT: unsupported chunk id\n");
195978ee8d1cSJulian Grajkowski 		return EINVAL;
196078ee8d1cSJulian Grajkowski 	}
196178ee8d1cSJulian Grajkowski 	mobj_hdr->obj_size = (unsigned int)obj_chunkhdr->size;
196278ee8d1cSJulian Grajkowski 	mobj_hdr->obj_name =
196378ee8d1cSJulian Grajkowski 	    (char *)(obj_chunkhdr->name + mobj_handle->sym_str);
196478ee8d1cSJulian Grajkowski 	return 0;
196578ee8d1cSJulian Grajkowski }
196678ee8d1cSJulian Grajkowski 
196778ee8d1cSJulian Grajkowski static int
qat_uclo_map_objs_from_mof(struct icp_qat_mof_handle * mobj_handle)196878ee8d1cSJulian Grajkowski qat_uclo_map_objs_from_mof(struct icp_qat_mof_handle *mobj_handle)
196978ee8d1cSJulian Grajkowski {
197078ee8d1cSJulian Grajkowski 	struct icp_qat_mof_objhdr *mof_obj_hdr;
197178ee8d1cSJulian Grajkowski 	const struct icp_qat_mof_obj_hdr *uobj_hdr;
197278ee8d1cSJulian Grajkowski 	const struct icp_qat_mof_obj_hdr *sobj_hdr;
197378ee8d1cSJulian Grajkowski 	struct icp_qat_mof_obj_chunkhdr *uobj_chunkhdr;
197478ee8d1cSJulian Grajkowski 	struct icp_qat_mof_obj_chunkhdr *sobj_chunkhdr;
197578ee8d1cSJulian Grajkowski 	unsigned int uobj_chunk_num = 0, sobj_chunk_num = 0;
197678ee8d1cSJulian Grajkowski 	unsigned int *valid_chunks = 0;
197778ee8d1cSJulian Grajkowski 	int ret, i;
197878ee8d1cSJulian Grajkowski 
197978ee8d1cSJulian Grajkowski 	uobj_hdr = (const struct icp_qat_mof_obj_hdr *)mobj_handle->uobjs_hdr;
198078ee8d1cSJulian Grajkowski 	sobj_hdr = (const struct icp_qat_mof_obj_hdr *)mobj_handle->sobjs_hdr;
198178ee8d1cSJulian Grajkowski 	if (uobj_hdr)
198278ee8d1cSJulian Grajkowski 		uobj_chunk_num = uobj_hdr->num_chunks;
198378ee8d1cSJulian Grajkowski 	if (sobj_hdr)
198478ee8d1cSJulian Grajkowski 		sobj_chunk_num = sobj_hdr->num_chunks;
198578ee8d1cSJulian Grajkowski 
198678ee8d1cSJulian Grajkowski 	mof_obj_hdr = (struct icp_qat_mof_objhdr *)
198778ee8d1cSJulian Grajkowski 	    malloc((uobj_chunk_num + sobj_chunk_num) * sizeof(*mof_obj_hdr),
198878ee8d1cSJulian Grajkowski 		   M_QAT,
198978ee8d1cSJulian Grajkowski 		   M_WAITOK | M_ZERO);
199078ee8d1cSJulian Grajkowski 
199178ee8d1cSJulian Grajkowski 	mobj_handle->obj_table.obj_hdr = mof_obj_hdr;
199278ee8d1cSJulian Grajkowski 	valid_chunks = &mobj_handle->obj_table.num_objs;
199378ee8d1cSJulian Grajkowski 	uobj_chunkhdr =
199478ee8d1cSJulian Grajkowski 	    (struct icp_qat_mof_obj_chunkhdr *)((uintptr_t)uobj_hdr +
199578ee8d1cSJulian Grajkowski 						sizeof(*uobj_hdr));
199678ee8d1cSJulian Grajkowski 	sobj_chunkhdr =
199778ee8d1cSJulian Grajkowski 	    (struct icp_qat_mof_obj_chunkhdr *)((uintptr_t)sobj_hdr +
199878ee8d1cSJulian Grajkowski 						sizeof(*sobj_hdr));
199978ee8d1cSJulian Grajkowski 
200078ee8d1cSJulian Grajkowski 	/* map uof objects */
200178ee8d1cSJulian Grajkowski 	for (i = 0; i < uobj_chunk_num; i++) {
200278ee8d1cSJulian Grajkowski 		ret = qat_uclo_map_obj_from_mof(mobj_handle,
200378ee8d1cSJulian Grajkowski 						&mof_obj_hdr[*valid_chunks],
200478ee8d1cSJulian Grajkowski 						&uobj_chunkhdr[i]);
200578ee8d1cSJulian Grajkowski 		if (ret)
200678ee8d1cSJulian Grajkowski 			return ret;
200778ee8d1cSJulian Grajkowski 		(*valid_chunks)++;
200878ee8d1cSJulian Grajkowski 	}
200978ee8d1cSJulian Grajkowski 
201078ee8d1cSJulian Grajkowski 	/* map suof objects */
201178ee8d1cSJulian Grajkowski 	for (i = 0; i < sobj_chunk_num; i++) {
201278ee8d1cSJulian Grajkowski 		ret = qat_uclo_map_obj_from_mof(mobj_handle,
201378ee8d1cSJulian Grajkowski 						&mof_obj_hdr[*valid_chunks],
201478ee8d1cSJulian Grajkowski 						&sobj_chunkhdr[i]);
201578ee8d1cSJulian Grajkowski 		if (ret)
201678ee8d1cSJulian Grajkowski 			return ret;
201778ee8d1cSJulian Grajkowski 		(*valid_chunks)++;
201878ee8d1cSJulian Grajkowski 	}
201978ee8d1cSJulian Grajkowski 
202078ee8d1cSJulian Grajkowski 	if ((uobj_chunk_num + sobj_chunk_num) != *valid_chunks) {
202178ee8d1cSJulian Grajkowski 		pr_err("QAT: inconsistent UOF/SUOF chunk amount\n");
202278ee8d1cSJulian Grajkowski 		return EINVAL;
202378ee8d1cSJulian Grajkowski 	}
202478ee8d1cSJulian Grajkowski 	return 0;
202578ee8d1cSJulian Grajkowski }
202678ee8d1cSJulian Grajkowski 
202778ee8d1cSJulian Grajkowski static void
qat_uclo_map_mof_symobjs(struct icp_qat_mof_handle * mobj_handle,struct icp_qat_mof_chunkhdr * mof_chunkhdr)202878ee8d1cSJulian Grajkowski qat_uclo_map_mof_symobjs(struct icp_qat_mof_handle *mobj_handle,
202978ee8d1cSJulian Grajkowski 			 struct icp_qat_mof_chunkhdr *mof_chunkhdr)
203078ee8d1cSJulian Grajkowski {
203178ee8d1cSJulian Grajkowski 	char **sym_str = (char **)&mobj_handle->sym_str;
203278ee8d1cSJulian Grajkowski 	unsigned int *sym_size = &mobj_handle->sym_size;
203378ee8d1cSJulian Grajkowski 	struct icp_qat_mof_str_table *str_table_obj;
203478ee8d1cSJulian Grajkowski 
203578ee8d1cSJulian Grajkowski 	*sym_size = *(unsigned int *)(uintptr_t)(mof_chunkhdr->offset +
203678ee8d1cSJulian Grajkowski 						 mobj_handle->mof_buf);
203778ee8d1cSJulian Grajkowski 	*sym_str =
203878ee8d1cSJulian Grajkowski 	    (char *)(uintptr_t)(mobj_handle->mof_buf + mof_chunkhdr->offset +
203978ee8d1cSJulian Grajkowski 				sizeof(str_table_obj->tab_len));
204078ee8d1cSJulian Grajkowski }
204178ee8d1cSJulian Grajkowski 
204278ee8d1cSJulian Grajkowski static void
qat_uclo_map_mof_chunk(struct icp_qat_mof_handle * mobj_handle,struct icp_qat_mof_chunkhdr * mof_chunkhdr)204378ee8d1cSJulian Grajkowski qat_uclo_map_mof_chunk(struct icp_qat_mof_handle *mobj_handle,
204478ee8d1cSJulian Grajkowski 		       struct icp_qat_mof_chunkhdr *mof_chunkhdr)
204578ee8d1cSJulian Grajkowski {
204678ee8d1cSJulian Grajkowski 	if (!strncmp(mof_chunkhdr->chunk_id,
204778ee8d1cSJulian Grajkowski 		     ICP_QAT_MOF_SYM_OBJS,
204878ee8d1cSJulian Grajkowski 		     ICP_QAT_MOF_OBJ_ID_LEN))
204978ee8d1cSJulian Grajkowski 		qat_uclo_map_mof_symobjs(mobj_handle, mof_chunkhdr);
205078ee8d1cSJulian Grajkowski 	else if (!strncmp(mof_chunkhdr->chunk_id,
205178ee8d1cSJulian Grajkowski 			  ICP_QAT_UOF_OBJS,
205278ee8d1cSJulian Grajkowski 			  ICP_QAT_MOF_OBJ_ID_LEN))
205378ee8d1cSJulian Grajkowski 		mobj_handle->uobjs_hdr =
205478ee8d1cSJulian Grajkowski 		    mobj_handle->mof_buf + (unsigned long)mof_chunkhdr->offset;
205578ee8d1cSJulian Grajkowski 	else if (!strncmp(mof_chunkhdr->chunk_id,
205678ee8d1cSJulian Grajkowski 			  ICP_QAT_SUOF_OBJS,
205778ee8d1cSJulian Grajkowski 			  ICP_QAT_MOF_OBJ_ID_LEN))
205878ee8d1cSJulian Grajkowski 		mobj_handle->sobjs_hdr =
205978ee8d1cSJulian Grajkowski 		    mobj_handle->mof_buf + (unsigned long)mof_chunkhdr->offset;
206078ee8d1cSJulian Grajkowski }
206178ee8d1cSJulian Grajkowski 
206278ee8d1cSJulian Grajkowski static int
qat_uclo_check_mof_format(const struct icp_qat_mof_file_hdr * mof_hdr)206378ee8d1cSJulian Grajkowski qat_uclo_check_mof_format(const struct icp_qat_mof_file_hdr *mof_hdr)
206478ee8d1cSJulian Grajkowski {
206578ee8d1cSJulian Grajkowski 	int maj = mof_hdr->maj_ver & 0xff;
206678ee8d1cSJulian Grajkowski 	int min = mof_hdr->min_ver & 0xff;
206778ee8d1cSJulian Grajkowski 
206878ee8d1cSJulian Grajkowski 	if (mof_hdr->file_id != ICP_QAT_MOF_FID) {
206978ee8d1cSJulian Grajkowski 		pr_err("QAT: invalid header 0x%x\n", mof_hdr->file_id);
207078ee8d1cSJulian Grajkowski 		return EINVAL;
207178ee8d1cSJulian Grajkowski 	}
207278ee8d1cSJulian Grajkowski 
207378ee8d1cSJulian Grajkowski 	if (mof_hdr->num_chunks <= 0x1) {
207478ee8d1cSJulian Grajkowski 		pr_err("QAT: MOF chunk amount is incorrect\n");
207578ee8d1cSJulian Grajkowski 		return EINVAL;
207678ee8d1cSJulian Grajkowski 	}
207778ee8d1cSJulian Grajkowski 	if (maj != ICP_QAT_MOF_MAJVER || min != ICP_QAT_MOF_MINVER) {
207878ee8d1cSJulian Grajkowski 		pr_err("QAT: bad MOF version, major 0x%x, minor 0x%x\n",
207978ee8d1cSJulian Grajkowski 		       maj,
208078ee8d1cSJulian Grajkowski 		       min);
208178ee8d1cSJulian Grajkowski 		return EINVAL;
208278ee8d1cSJulian Grajkowski 	}
208378ee8d1cSJulian Grajkowski 	return 0;
208478ee8d1cSJulian Grajkowski }
208578ee8d1cSJulian Grajkowski 
208678ee8d1cSJulian Grajkowski static int
qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle * handle,const struct icp_qat_mof_file_hdr * mof_ptr,u32 mof_size,const char * obj_name,const char ** obj_ptr,unsigned int * obj_size)208778ee8d1cSJulian Grajkowski qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle,
208878ee8d1cSJulian Grajkowski 		     const struct icp_qat_mof_file_hdr *mof_ptr,
208978ee8d1cSJulian Grajkowski 		     u32 mof_size,
209078ee8d1cSJulian Grajkowski 		     const char *obj_name,
209178ee8d1cSJulian Grajkowski 		     const char **obj_ptr,
209278ee8d1cSJulian Grajkowski 		     unsigned int *obj_size)
209378ee8d1cSJulian Grajkowski {
209478ee8d1cSJulian Grajkowski 	struct icp_qat_mof_handle *mobj_handle;
209578ee8d1cSJulian Grajkowski 	struct icp_qat_mof_chunkhdr *mof_chunkhdr;
209678ee8d1cSJulian Grajkowski 	unsigned short chunks_num;
209778ee8d1cSJulian Grajkowski 	int ret;
209878ee8d1cSJulian Grajkowski 	unsigned int i;
209978ee8d1cSJulian Grajkowski 
210078ee8d1cSJulian Grajkowski 	if (mof_ptr->file_id == ICP_QAT_UOF_FID ||
210178ee8d1cSJulian Grajkowski 	    mof_ptr->file_id == ICP_QAT_SUOF_FID) {
210278ee8d1cSJulian Grajkowski 		if (obj_ptr)
210378ee8d1cSJulian Grajkowski 			*obj_ptr = (const char *)mof_ptr;
210478ee8d1cSJulian Grajkowski 		if (obj_size)
210578ee8d1cSJulian Grajkowski 			*obj_size = (unsigned int)mof_size;
210678ee8d1cSJulian Grajkowski 		return 0;
210778ee8d1cSJulian Grajkowski 	}
210878ee8d1cSJulian Grajkowski 	if (qat_uclo_check_mof_format(mof_ptr))
210978ee8d1cSJulian Grajkowski 		return EINVAL;
211078ee8d1cSJulian Grajkowski 	mobj_handle = malloc(sizeof(*mobj_handle), M_QAT, M_WAITOK | M_ZERO);
211178ee8d1cSJulian Grajkowski 	handle->mobj_handle = mobj_handle;
211278ee8d1cSJulian Grajkowski 	ret = qat_uclo_map_mof_file_hdr(handle, mof_ptr, mof_size);
211378ee8d1cSJulian Grajkowski 	if (ret)
211478ee8d1cSJulian Grajkowski 		return ret;
211578ee8d1cSJulian Grajkowski 	mof_chunkhdr = (struct icp_qat_mof_chunkhdr *)((uintptr_t)mof_ptr +
211678ee8d1cSJulian Grajkowski 						       sizeof(*mof_ptr));
211778ee8d1cSJulian Grajkowski 	chunks_num = mof_ptr->num_chunks;
211878ee8d1cSJulian Grajkowski 	/*Parse MOF file chunks*/
211978ee8d1cSJulian Grajkowski 	for (i = 0; i < chunks_num; i++)
212078ee8d1cSJulian Grajkowski 		qat_uclo_map_mof_chunk(mobj_handle, &mof_chunkhdr[i]);
212178ee8d1cSJulian Grajkowski 	/*All sym_objs uobjs and sobjs should be available*/
212278ee8d1cSJulian Grajkowski 	if (!mobj_handle->sym_str ||
212378ee8d1cSJulian Grajkowski 	    (!mobj_handle->uobjs_hdr && !mobj_handle->sobjs_hdr))
212478ee8d1cSJulian Grajkowski 		return EINVAL;
212578ee8d1cSJulian Grajkowski 	ret = qat_uclo_map_objs_from_mof(mobj_handle);
212678ee8d1cSJulian Grajkowski 	if (ret)
212778ee8d1cSJulian Grajkowski 		return ret;
212878ee8d1cSJulian Grajkowski 	/*Seek specified uof object in MOF*/
212978ee8d1cSJulian Grajkowski 	ret = qat_uclo_seek_obj_inside_mof(mobj_handle,
213078ee8d1cSJulian Grajkowski 					   obj_name,
213178ee8d1cSJulian Grajkowski 					   obj_ptr,
213278ee8d1cSJulian Grajkowski 					   obj_size);
213378ee8d1cSJulian Grajkowski 	if (ret)
213478ee8d1cSJulian Grajkowski 		return ret;
213578ee8d1cSJulian Grajkowski 	return 0;
213678ee8d1cSJulian Grajkowski }
213778ee8d1cSJulian Grajkowski 
213878ee8d1cSJulian Grajkowski int
qat_uclo_map_obj(struct icp_qat_fw_loader_handle * handle,const void * addr_ptr,u32 mem_size,const char * obj_name)213978ee8d1cSJulian Grajkowski qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle,
214078ee8d1cSJulian Grajkowski 		 const void *addr_ptr,
214178ee8d1cSJulian Grajkowski 		 u32 mem_size,
214278ee8d1cSJulian Grajkowski 		 const char *obj_name)
214378ee8d1cSJulian Grajkowski {
214478ee8d1cSJulian Grajkowski 	const char *obj_addr;
214578ee8d1cSJulian Grajkowski 	u32 obj_size;
214678ee8d1cSJulian Grajkowski 	int ret;
214778ee8d1cSJulian Grajkowski 
214878ee8d1cSJulian Grajkowski 	BUILD_BUG_ON(ICP_QAT_UCLO_MAX_AE >
214978ee8d1cSJulian Grajkowski 		     (sizeof(handle->hal_handle->ae_mask) * 8));
215078ee8d1cSJulian Grajkowski 
215178ee8d1cSJulian Grajkowski 	if (!handle || !addr_ptr || mem_size < 24)
215278ee8d1cSJulian Grajkowski 		return EINVAL;
215378ee8d1cSJulian Grajkowski 
215478ee8d1cSJulian Grajkowski 	if (obj_name) {
215578ee8d1cSJulian Grajkowski 		ret = qat_uclo_map_mof_obj(
215678ee8d1cSJulian Grajkowski 		    handle, addr_ptr, mem_size, obj_name, &obj_addr, &obj_size);
215778ee8d1cSJulian Grajkowski 		if (ret)
215878ee8d1cSJulian Grajkowski 			return ret;
215978ee8d1cSJulian Grajkowski 	} else {
216078ee8d1cSJulian Grajkowski 		obj_addr = addr_ptr;
216178ee8d1cSJulian Grajkowski 		obj_size = mem_size;
216278ee8d1cSJulian Grajkowski 	}
216378ee8d1cSJulian Grajkowski 
216478ee8d1cSJulian Grajkowski 	return (handle->fw_auth) ?
216578ee8d1cSJulian Grajkowski 	    qat_uclo_map_suof_obj(handle, obj_addr, obj_size) :
216678ee8d1cSJulian Grajkowski 	    qat_uclo_map_uof_obj(handle, obj_addr, obj_size);
216778ee8d1cSJulian Grajkowski }
216878ee8d1cSJulian Grajkowski 
216978ee8d1cSJulian Grajkowski void
qat_uclo_del_obj(struct icp_qat_fw_loader_handle * handle)217078ee8d1cSJulian Grajkowski qat_uclo_del_obj(struct icp_qat_fw_loader_handle *handle)
217178ee8d1cSJulian Grajkowski {
217278ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
217378ee8d1cSJulian Grajkowski 	unsigned int a;
217478ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
217578ee8d1cSJulian Grajkowski 
217678ee8d1cSJulian Grajkowski 	if (handle->mobj_handle)
217778ee8d1cSJulian Grajkowski 		qat_uclo_del_mof(handle);
217878ee8d1cSJulian Grajkowski 	if (handle->sobj_handle)
217978ee8d1cSJulian Grajkowski 		qat_uclo_del_suof(handle);
218078ee8d1cSJulian Grajkowski 	if (!obj_handle)
218178ee8d1cSJulian Grajkowski 		return;
218278ee8d1cSJulian Grajkowski 
218378ee8d1cSJulian Grajkowski 	free(obj_handle->uword_buf, M_QAT);
218478ee8d1cSJulian Grajkowski 	for (a = 0; a < obj_handle->uimage_num; a++)
218578ee8d1cSJulian Grajkowski 		free(obj_handle->ae_uimage[a].page, M_QAT);
218678ee8d1cSJulian Grajkowski 
218778ee8d1cSJulian Grajkowski 	for_each_set_bit(a, &ae_mask, handle->hal_handle->ae_max_num)
218878ee8d1cSJulian Grajkowski 	{
218978ee8d1cSJulian Grajkowski 		qat_uclo_free_ae_data(&obj_handle->ae_data[a]);
219078ee8d1cSJulian Grajkowski 	}
219178ee8d1cSJulian Grajkowski 
219278ee8d1cSJulian Grajkowski 	free(obj_handle->obj_hdr, M_QAT);
219378ee8d1cSJulian Grajkowski 	free(obj_handle->obj_buf, M_QAT);
219478ee8d1cSJulian Grajkowski 	free(obj_handle, M_QAT);
219578ee8d1cSJulian Grajkowski 	handle->obj_handle = NULL;
219678ee8d1cSJulian Grajkowski }
219778ee8d1cSJulian Grajkowski 
219878ee8d1cSJulian Grajkowski static void
qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle * obj_handle,struct icp_qat_uclo_encap_page * encap_page,uint64_t * uword,unsigned int addr_p,unsigned int raddr,uint64_t fill)219978ee8d1cSJulian Grajkowski qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle *obj_handle,
220078ee8d1cSJulian Grajkowski 		     struct icp_qat_uclo_encap_page *encap_page,
220178ee8d1cSJulian Grajkowski 		     uint64_t *uword,
220278ee8d1cSJulian Grajkowski 		     unsigned int addr_p,
220378ee8d1cSJulian Grajkowski 		     unsigned int raddr,
220478ee8d1cSJulian Grajkowski 		     uint64_t fill)
220578ee8d1cSJulian Grajkowski {
220678ee8d1cSJulian Grajkowski 	uint64_t uwrd = 0;
220778ee8d1cSJulian Grajkowski 	unsigned int i, addr;
220878ee8d1cSJulian Grajkowski 
220978ee8d1cSJulian Grajkowski 	if (!encap_page) {
221078ee8d1cSJulian Grajkowski 		*uword = fill;
221178ee8d1cSJulian Grajkowski 		return;
221278ee8d1cSJulian Grajkowski 	}
221378ee8d1cSJulian Grajkowski 	addr = (encap_page->page_region) ? raddr : addr_p;
221478ee8d1cSJulian Grajkowski 	for (i = 0; i < encap_page->uwblock_num; i++) {
221578ee8d1cSJulian Grajkowski 		if (addr >= encap_page->uwblock[i].start_addr &&
221678ee8d1cSJulian Grajkowski 		    addr <= encap_page->uwblock[i].start_addr +
221778ee8d1cSJulian Grajkowski 			    encap_page->uwblock[i].words_num - 1) {
221878ee8d1cSJulian Grajkowski 			addr -= encap_page->uwblock[i].start_addr;
221978ee8d1cSJulian Grajkowski 			addr *= obj_handle->uword_in_bytes;
222078ee8d1cSJulian Grajkowski 			memcpy(&uwrd,
222178ee8d1cSJulian Grajkowski 			       (void *)(((uintptr_t)encap_page->uwblock[i]
222278ee8d1cSJulian Grajkowski 					     .micro_words) +
222378ee8d1cSJulian Grajkowski 					addr),
222478ee8d1cSJulian Grajkowski 			       obj_handle->uword_in_bytes);
222578ee8d1cSJulian Grajkowski 			uwrd = uwrd & 0xbffffffffffull;
222678ee8d1cSJulian Grajkowski 		}
222778ee8d1cSJulian Grajkowski 	}
222878ee8d1cSJulian Grajkowski 	*uword = uwrd;
222978ee8d1cSJulian Grajkowski 	if (*uword == INVLD_UWORD)
223078ee8d1cSJulian Grajkowski 		*uword = fill;
223178ee8d1cSJulian Grajkowski }
223278ee8d1cSJulian Grajkowski 
223378ee8d1cSJulian Grajkowski static void
qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uclo_encap_page * encap_page,unsigned int ae)223478ee8d1cSJulian Grajkowski qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle,
223578ee8d1cSJulian Grajkowski 			    struct icp_qat_uclo_encap_page *encap_page,
223678ee8d1cSJulian Grajkowski 			    unsigned int ae)
223778ee8d1cSJulian Grajkowski {
223878ee8d1cSJulian Grajkowski 	unsigned int uw_physical_addr, uw_relative_addr, i, words_num, cpylen;
223978ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
224078ee8d1cSJulian Grajkowski 	uint64_t fill_pat;
224178ee8d1cSJulian Grajkowski 
224278ee8d1cSJulian Grajkowski 	/* load the page starting at appropriate ustore address */
224378ee8d1cSJulian Grajkowski 	/* get fill-pattern from an image -- they are all the same */
224478ee8d1cSJulian Grajkowski 	memcpy(&fill_pat,
224578ee8d1cSJulian Grajkowski 	       obj_handle->ae_uimage[0].img_ptr->fill_pattern,
224678ee8d1cSJulian Grajkowski 	       sizeof(uint64_t));
224778ee8d1cSJulian Grajkowski 	uw_physical_addr = encap_page->beg_addr_p;
224878ee8d1cSJulian Grajkowski 	uw_relative_addr = 0;
224978ee8d1cSJulian Grajkowski 	words_num = encap_page->micro_words_num;
225078ee8d1cSJulian Grajkowski 	while (words_num) {
225178ee8d1cSJulian Grajkowski 		if (words_num < UWORD_CPYBUF_SIZE)
225278ee8d1cSJulian Grajkowski 			cpylen = words_num;
225378ee8d1cSJulian Grajkowski 		else
225478ee8d1cSJulian Grajkowski 			cpylen = UWORD_CPYBUF_SIZE;
225578ee8d1cSJulian Grajkowski 
225678ee8d1cSJulian Grajkowski 		/* load the buffer */
225778ee8d1cSJulian Grajkowski 		for (i = 0; i < cpylen; i++)
225878ee8d1cSJulian Grajkowski 			qat_uclo_fill_uwords(obj_handle,
225978ee8d1cSJulian Grajkowski 					     encap_page,
226078ee8d1cSJulian Grajkowski 					     &obj_handle->uword_buf[i],
226178ee8d1cSJulian Grajkowski 					     uw_physical_addr + i,
226278ee8d1cSJulian Grajkowski 					     uw_relative_addr + i,
226378ee8d1cSJulian Grajkowski 					     fill_pat);
226478ee8d1cSJulian Grajkowski 
2265a977168cSMichal Gulbicki 		if (obj_handle->ae_data[ae].shareable_ustore &&
2266a977168cSMichal Gulbicki 		    !IS_QAT_GEN4(pci_get_device(GET_DEV(handle->accel_dev))))
226778ee8d1cSJulian Grajkowski 			/* copy the buffer to ustore */
226878ee8d1cSJulian Grajkowski 			qat_hal_wr_coalesce_uwords(handle,
226978ee8d1cSJulian Grajkowski 						   (unsigned char)ae,
227078ee8d1cSJulian Grajkowski 						   uw_physical_addr,
227178ee8d1cSJulian Grajkowski 						   cpylen,
227278ee8d1cSJulian Grajkowski 						   obj_handle->uword_buf);
227378ee8d1cSJulian Grajkowski 		else
227478ee8d1cSJulian Grajkowski 			/* copy the buffer to ustore */
227578ee8d1cSJulian Grajkowski 			qat_hal_wr_uwords(handle,
227678ee8d1cSJulian Grajkowski 					  (unsigned char)ae,
227778ee8d1cSJulian Grajkowski 					  uw_physical_addr,
227878ee8d1cSJulian Grajkowski 					  cpylen,
227978ee8d1cSJulian Grajkowski 					  obj_handle->uword_buf);
228078ee8d1cSJulian Grajkowski 		uw_physical_addr += cpylen;
228178ee8d1cSJulian Grajkowski 		uw_relative_addr += cpylen;
228278ee8d1cSJulian Grajkowski 		words_num -= cpylen;
228378ee8d1cSJulian Grajkowski 	}
228478ee8d1cSJulian Grajkowski }
228578ee8d1cSJulian Grajkowski 
228678ee8d1cSJulian Grajkowski static void
qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle * handle,struct icp_qat_uof_image * image)228778ee8d1cSJulian Grajkowski qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle *handle,
228878ee8d1cSJulian Grajkowski 			struct icp_qat_uof_image *image)
228978ee8d1cSJulian Grajkowski {
229078ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
229178ee8d1cSJulian Grajkowski 	unsigned int ctx_mask, s;
229278ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_page *page;
229378ee8d1cSJulian Grajkowski 	unsigned char ae = 0;
229478ee8d1cSJulian Grajkowski 	int ctx;
229578ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_aedata *aed;
229678ee8d1cSJulian Grajkowski 	unsigned long ae_mask = handle->hal_handle->ae_mask;
229778ee8d1cSJulian Grajkowski 
229878ee8d1cSJulian Grajkowski 	if (ICP_QAT_CTX_MODE(image->ae_mode) == ICP_QAT_UCLO_MAX_CTX)
229978ee8d1cSJulian Grajkowski 		ctx_mask = 0xff;
230078ee8d1cSJulian Grajkowski 	else
230178ee8d1cSJulian Grajkowski 		ctx_mask = 0x55;
230278ee8d1cSJulian Grajkowski 	/* load the default page and set assigned CTX PC
230378ee8d1cSJulian Grajkowski 	 * to the entrypoint address
230478ee8d1cSJulian Grajkowski 	 */
230578ee8d1cSJulian Grajkowski 	for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num)
230678ee8d1cSJulian Grajkowski 	{
230778ee8d1cSJulian Grajkowski 		unsigned long cfg_ae_mask = handle->cfg_ae_mask;
230878ee8d1cSJulian Grajkowski 		unsigned long ae_assigned = image->ae_assigned;
230978ee8d1cSJulian Grajkowski 
231078ee8d1cSJulian Grajkowski 		if (!test_bit(ae, &cfg_ae_mask))
231178ee8d1cSJulian Grajkowski 			continue;
231278ee8d1cSJulian Grajkowski 
231378ee8d1cSJulian Grajkowski 		if (!test_bit(ae, &ae_assigned))
231478ee8d1cSJulian Grajkowski 			continue;
231578ee8d1cSJulian Grajkowski 
231678ee8d1cSJulian Grajkowski 		aed = &obj_handle->ae_data[ae];
231778ee8d1cSJulian Grajkowski 		/* find the slice to which this image is assigned */
231878ee8d1cSJulian Grajkowski 		for (s = 0; s < aed->slice_num; s++) {
231978ee8d1cSJulian Grajkowski 			if (image->ctx_assigned &
232078ee8d1cSJulian Grajkowski 			    aed->ae_slices[s].ctx_mask_assigned)
232178ee8d1cSJulian Grajkowski 				break;
232278ee8d1cSJulian Grajkowski 		}
232378ee8d1cSJulian Grajkowski 		if (s >= aed->slice_num)
232478ee8d1cSJulian Grajkowski 			continue;
232578ee8d1cSJulian Grajkowski 		page = aed->ae_slices[s].page;
232678ee8d1cSJulian Grajkowski 		if (!page->encap_page->def_page)
232778ee8d1cSJulian Grajkowski 			continue;
232878ee8d1cSJulian Grajkowski 		qat_uclo_wr_uimage_raw_page(handle, page->encap_page, ae);
232978ee8d1cSJulian Grajkowski 
233078ee8d1cSJulian Grajkowski 		page = aed->ae_slices[s].page;
233178ee8d1cSJulian Grajkowski 		for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++)
233278ee8d1cSJulian Grajkowski 			aed->ae_slices[s].cur_page[ctx] =
233378ee8d1cSJulian Grajkowski 			    (ctx_mask & (1 << ctx)) ? page : NULL;
233478ee8d1cSJulian Grajkowski 		qat_hal_set_live_ctx(handle,
233578ee8d1cSJulian Grajkowski 				     (unsigned char)ae,
233678ee8d1cSJulian Grajkowski 				     image->ctx_assigned);
233778ee8d1cSJulian Grajkowski 		qat_hal_set_pc(handle,
233878ee8d1cSJulian Grajkowski 			       (unsigned char)ae,
233978ee8d1cSJulian Grajkowski 			       image->ctx_assigned,
234078ee8d1cSJulian Grajkowski 			       image->entry_address);
234178ee8d1cSJulian Grajkowski 	}
234278ee8d1cSJulian Grajkowski }
234378ee8d1cSJulian Grajkowski 
234478ee8d1cSJulian Grajkowski static int
qat_uclo_wr_suof_img(struct icp_qat_fw_loader_handle * handle)234578ee8d1cSJulian Grajkowski qat_uclo_wr_suof_img(struct icp_qat_fw_loader_handle *handle)
234678ee8d1cSJulian Grajkowski {
234778ee8d1cSJulian Grajkowski 	unsigned int i;
234878ee8d1cSJulian Grajkowski 	struct icp_qat_fw_auth_desc *desc = NULL;
234978ee8d1cSJulian Grajkowski 	struct icp_firml_dram_desc img_desc;
235078ee8d1cSJulian Grajkowski 	struct icp_qat_suof_handle *sobj_handle = handle->sobj_handle;
235178ee8d1cSJulian Grajkowski 	struct icp_qat_suof_img_hdr *simg_hdr = sobj_handle->img_table.simg_hdr;
235278ee8d1cSJulian Grajkowski 
235378ee8d1cSJulian Grajkowski 	for (i = 0; i < sobj_handle->img_table.num_simgs; i++) {
235478ee8d1cSJulian Grajkowski 		if (qat_uclo_map_auth_fw(handle,
235578ee8d1cSJulian Grajkowski 					 (const char *)simg_hdr[i].simg_buf,
235678ee8d1cSJulian Grajkowski 					 (unsigned int)(simg_hdr[i].simg_len),
235778ee8d1cSJulian Grajkowski 					 &img_desc,
235878ee8d1cSJulian Grajkowski 					 &desc))
235978ee8d1cSJulian Grajkowski 			goto wr_err;
236078ee8d1cSJulian Grajkowski 		if (qat_uclo_auth_fw(handle, desc))
236178ee8d1cSJulian Grajkowski 			goto wr_err;
2362a977168cSMichal Gulbicki 		if (qat_uclo_is_broadcast(handle, i)) {
2363a977168cSMichal Gulbicki 			if (qat_uclo_broadcast_load_fw(handle, desc))
2364a977168cSMichal Gulbicki 				goto wr_err;
2365a977168cSMichal Gulbicki 		} else {
236678ee8d1cSJulian Grajkowski 			if (qat_uclo_load_fw(handle, desc))
236778ee8d1cSJulian Grajkowski 				goto wr_err;
2368a977168cSMichal Gulbicki 		}
236978ee8d1cSJulian Grajkowski 		qat_uclo_simg_free(handle, &img_desc);
237078ee8d1cSJulian Grajkowski 	}
2371a977168cSMichal Gulbicki 
237278ee8d1cSJulian Grajkowski 	return 0;
237378ee8d1cSJulian Grajkowski wr_err:
237478ee8d1cSJulian Grajkowski 	qat_uclo_simg_free(handle, &img_desc);
237578ee8d1cSJulian Grajkowski 	return -EINVAL;
237678ee8d1cSJulian Grajkowski }
237778ee8d1cSJulian Grajkowski 
237878ee8d1cSJulian Grajkowski static int
qat_uclo_wr_uof_img(struct icp_qat_fw_loader_handle * handle)237978ee8d1cSJulian Grajkowski qat_uclo_wr_uof_img(struct icp_qat_fw_loader_handle *handle)
238078ee8d1cSJulian Grajkowski {
238178ee8d1cSJulian Grajkowski 	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
238278ee8d1cSJulian Grajkowski 	unsigned int i;
238378ee8d1cSJulian Grajkowski 
238478ee8d1cSJulian Grajkowski 	if (qat_uclo_init_globals(handle))
238578ee8d1cSJulian Grajkowski 		return EINVAL;
238678ee8d1cSJulian Grajkowski 	for (i = 0; i < obj_handle->uimage_num; i++) {
238778ee8d1cSJulian Grajkowski 		if (!obj_handle->ae_uimage[i].img_ptr)
238878ee8d1cSJulian Grajkowski 			return EINVAL;
238978ee8d1cSJulian Grajkowski 		if (qat_uclo_init_ustore(handle, &obj_handle->ae_uimage[i]))
239078ee8d1cSJulian Grajkowski 			return EINVAL;
239178ee8d1cSJulian Grajkowski 		qat_uclo_wr_uimage_page(handle,
239278ee8d1cSJulian Grajkowski 					obj_handle->ae_uimage[i].img_ptr);
239378ee8d1cSJulian Grajkowski 	}
239478ee8d1cSJulian Grajkowski 	return 0;
239578ee8d1cSJulian Grajkowski }
239678ee8d1cSJulian Grajkowski 
239778ee8d1cSJulian Grajkowski int
qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle * handle)239878ee8d1cSJulian Grajkowski qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle)
239978ee8d1cSJulian Grajkowski {
240078ee8d1cSJulian Grajkowski 	return (handle->fw_auth) ? qat_uclo_wr_suof_img(handle) :
240178ee8d1cSJulian Grajkowski 				   qat_uclo_wr_uof_img(handle);
240278ee8d1cSJulian Grajkowski }
240378ee8d1cSJulian Grajkowski 
240478ee8d1cSJulian Grajkowski int
qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle * handle,unsigned int cfg_ae_mask)240578ee8d1cSJulian Grajkowski qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle,
240678ee8d1cSJulian Grajkowski 			 unsigned int cfg_ae_mask)
240778ee8d1cSJulian Grajkowski {
240878ee8d1cSJulian Grajkowski 	if (!cfg_ae_mask)
240978ee8d1cSJulian Grajkowski 		return EINVAL;
241078ee8d1cSJulian Grajkowski 
241178ee8d1cSJulian Grajkowski 	handle->cfg_ae_mask = cfg_ae_mask;
241278ee8d1cSJulian Grajkowski 	return 0;
241378ee8d1cSJulian Grajkowski }
2414