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