blob: 258009178031d6a768c79a59bc74de8fac179b36 [file] [log] [blame]
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001/*
2 This file is provided under a dual BSD/GPLv2 license. When using or
3 redistributing this file, you may do so under either license.
4
5 GPL LICENSE SUMMARY
6 Copyright(c) 2014 Intel Corporation.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of version 2 of the GNU General Public License as
9 published by the Free Software Foundation.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 Contact Information:
17 qat-linux@intel.com
18
19 BSD LICENSE
20 Copyright(c) 2014 Intel Corporation.
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions
23 are met:
24
25 * Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27 * Redistributions in binary form must reproduce the above copyright
28 notice, this list of conditions and the following disclaimer in
29 the documentation and/or other materials provided with the
30 distribution.
31 * Neither the name of Intel Corporation nor the names of its
32 contributors may be used to endorse or promote products derived
33 from this software without specific prior written permission.
34
35 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46*/
47#include <linux/slab.h>
48#include <linux/ctype.h>
49#include <linux/kernel.h>
50
51#include "adf_accel_devices.h"
52#include "adf_common_drv.h"
53#include "icp_qat_uclo.h"
54#include "icp_qat_hal.h"
55#include "icp_qat_fw_loader_handle.h"
56
57#define UWORD_CPYBUF_SIZE 1024
58#define INVLD_UWORD 0xffffffffffull
59#define PID_MINOR_REV 0xf
60#define PID_MAJOR_REV (0xf << 4)
61
62static int qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle *obj_handle,
63 unsigned int ae, unsigned int image_num)
64{
65 struct icp_qat_uclo_aedata *ae_data;
66 struct icp_qat_uclo_encapme *encap_image;
67 struct icp_qat_uclo_page *page = NULL;
68 struct icp_qat_uclo_aeslice *ae_slice = NULL;
69
70 ae_data = &obj_handle->ae_data[ae];
71 encap_image = &obj_handle->ae_uimage[image_num];
72 ae_slice = &ae_data->ae_slices[ae_data->slice_num];
73 ae_slice->encap_image = encap_image;
74
75 if (encap_image->img_ptr) {
76 ae_slice->ctx_mask_assigned =
77 encap_image->img_ptr->ctx_assigned;
78 ae_data->eff_ustore_size = obj_handle->ustore_phy_size;
79 } else {
80 ae_slice->ctx_mask_assigned = 0;
81 }
Tadeusz Struk8c1f8e32014-07-25 15:55:41 -070082 ae_slice->region = kzalloc(sizeof(*ae_slice->region), GFP_KERNEL);
83 if (!ae_slice->region)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -070084 return -ENOMEM;
Tadeusz Struk45cff262014-07-25 15:55:26 -070085 ae_slice->page = kzalloc(sizeof(*ae_slice->page), GFP_KERNEL);
86 if (!ae_slice->page)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -070087 goto out_err;
88 page = ae_slice->page;
89 page->encap_page = encap_image->page;
Tadeusz Struk8c1f8e32014-07-25 15:55:41 -070090 ae_slice->page->region = ae_slice->region;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -070091 ae_data->slice_num++;
92 return 0;
93out_err:
Tadeusz Struk8c1f8e32014-07-25 15:55:41 -070094 kfree(ae_slice->region);
95 ae_slice->region = NULL;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -070096 return -ENOMEM;
97}
98
99static int qat_uclo_free_ae_data(struct icp_qat_uclo_aedata *ae_data)
100{
Tadeusz Struk8c1f8e32014-07-25 15:55:41 -0700101 unsigned int i;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700102
103 if (!ae_data) {
104 pr_err("QAT: bad argument, ae_data is NULL\n ");
105 return -EINVAL;
106 }
107
Tadeusz Struk8c1f8e32014-07-25 15:55:41 -0700108 for (i = 0; i < ae_data->slice_num; i++) {
109 kfree(ae_data->ae_slices[i].region);
110 ae_data->ae_slices[i].region = NULL;
111 kfree(ae_data->ae_slices[i].page);
112 ae_data->ae_slices[i].page = NULL;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700113 }
114 return 0;
115}
116
117static char *qat_uclo_get_string(struct icp_qat_uof_strtable *str_table,
118 unsigned int str_offset)
119{
120 if ((!str_table->table_len) || (str_offset > str_table->table_len))
121 return NULL;
122 return (char *)(((unsigned long)(str_table->strings)) + str_offset);
123}
124
125static int qat_uclo_check_format(struct icp_qat_uof_filehdr *hdr)
126{
127 int maj = hdr->maj_ver & 0xff;
128 int min = hdr->min_ver & 0xff;
129
130 if (hdr->file_id != ICP_QAT_UOF_FID) {
131 pr_err("QAT: Invalid header 0x%x\n", hdr->file_id);
132 return -EINVAL;
133 }
134 if (min != ICP_QAT_UOF_MINVER || maj != ICP_QAT_UOF_MAJVER) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700135 pr_err("QAT: bad UOF version, major 0x%x, minor 0x%x\n",
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700136 maj, min);
137 return -EINVAL;
138 }
139 return 0;
140}
141
142static void qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle *handle,
143 unsigned int addr, unsigned int *val,
144 unsigned int num_in_bytes)
145{
146 unsigned int outval;
147 unsigned char *ptr = (unsigned char *)val;
148
149 while (num_in_bytes) {
150 memcpy(&outval, ptr, 4);
151 SRAM_WRITE(handle, addr, outval);
152 num_in_bytes -= 4;
153 ptr += 4;
154 addr += 4;
155 }
156}
157
158static void qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle *handle,
159 unsigned char ae, unsigned int addr,
160 unsigned int *val,
161 unsigned int num_in_bytes)
162{
163 unsigned int outval;
164 unsigned char *ptr = (unsigned char *)val;
165
166 addr >>= 0x2; /* convert to uword address */
167
168 while (num_in_bytes) {
169 memcpy(&outval, ptr, 4);
170 qat_hal_wr_umem(handle, ae, addr++, 1, &outval);
171 num_in_bytes -= 4;
172 ptr += 4;
173 }
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700174}
175
176static void qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle *handle,
177 unsigned char ae,
178 struct icp_qat_uof_batch_init
179 *umem_init_header)
180{
181 struct icp_qat_uof_batch_init *umem_init;
182
183 if (!umem_init_header)
184 return;
185 umem_init = umem_init_header->next;
186 while (umem_init) {
187 unsigned int addr, *value, size;
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700188
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700189 ae = umem_init->ae;
190 addr = umem_init->addr;
191 value = umem_init->value;
192 size = umem_init->size;
193 qat_uclo_wr_umem_by_words(handle, ae, addr, value, size);
194 umem_init = umem_init->next;
195 }
196}
197
198static void
199qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,
200 struct icp_qat_uof_batch_init **base)
201{
202 struct icp_qat_uof_batch_init *umem_init;
203
204 umem_init = *base;
205 while (umem_init) {
206 struct icp_qat_uof_batch_init *pre;
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700207
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700208 pre = umem_init;
209 umem_init = umem_init->next;
210 kfree(pre);
211 }
212 *base = NULL;
213}
214
215static int qat_uclo_parse_num(char *str, unsigned int *num)
216{
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700217 char buf[16] = {0};
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700218 unsigned long ae = 0;
219 int i;
220
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700221 strncpy(buf, str, 15);
222 for (i = 0; i < 16; i++) {
223 if (!isdigit(buf[i])) {
224 buf[i] = '\0';
225 break;
226 }
227 }
228 if ((kstrtoul(buf, 10, &ae)))
229 return -EFAULT;
230
231 *num = (unsigned int)ae;
232 return 0;
233}
234
235static int qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle *handle,
236 struct icp_qat_uof_initmem *init_mem,
237 unsigned int size_range, unsigned int *ae)
238{
239 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
240 char *str;
241
242 if ((init_mem->addr + init_mem->num_in_bytes) > (size_range << 0x2)) {
243 pr_err("QAT: initmem is out of range");
244 return -EINVAL;
245 }
246 if (init_mem->scope != ICP_QAT_UOF_LOCAL_SCOPE) {
247 pr_err("QAT: Memory scope for init_mem error\n");
248 return -EINVAL;
249 }
Tadeusz Struk45cff262014-07-25 15:55:26 -0700250 str = qat_uclo_get_string(&obj_handle->str_table, init_mem->sym_name);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700251 if (!str) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700252 pr_err("QAT: AE name assigned in UOF init table is NULL\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700253 return -EINVAL;
254 }
255 if (qat_uclo_parse_num(str, ae)) {
256 pr_err("QAT: Parse num for AE number failed\n");
257 return -EINVAL;
258 }
Tadeusz Struk45cff262014-07-25 15:55:26 -0700259 if (!test_bit(*ae, (unsigned long *)&handle->hal_handle->ae_mask)) {
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700260 pr_err("QAT: ae %d to be init is fused off\n", *ae);
261 return -EINVAL;
262 }
263 if (*ae >= ICP_QAT_UCLO_MAX_AE) {
264 pr_err("QAT: ae %d out of range\n", *ae);
265 return -EINVAL;
266 }
267 return 0;
268}
269
270static int qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle
271 *handle, struct icp_qat_uof_initmem
272 *init_mem, unsigned int ae,
273 struct icp_qat_uof_batch_init
274 **init_tab_base)
275{
276 struct icp_qat_uof_batch_init *init_header, *tail;
277 struct icp_qat_uof_batch_init *mem_init, *tail_old;
278 struct icp_qat_uof_memvar_attr *mem_val_attr;
279 unsigned int i, flag = 0;
280
281 mem_val_attr =
282 (struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
283 sizeof(struct icp_qat_uof_initmem));
284
285 init_header = *init_tab_base;
286 if (!init_header) {
287 init_header = kzalloc(sizeof(*init_header), GFP_KERNEL);
288 if (!init_header)
289 return -ENOMEM;
290 init_header->size = 1;
291 *init_tab_base = init_header;
292 flag = 1;
293 }
294 tail_old = init_header;
295 while (tail_old->next)
296 tail_old = tail_old->next;
297 tail = tail_old;
298 for (i = 0; i < init_mem->val_attr_num; i++) {
299 mem_init = kzalloc(sizeof(*mem_init), GFP_KERNEL);
300 if (!mem_init)
301 goto out_err;
302 mem_init->ae = ae;
303 mem_init->addr = init_mem->addr + mem_val_attr->offset_in_byte;
304 mem_init->value = &mem_val_attr->value;
305 mem_init->size = 4;
306 mem_init->next = NULL;
307 tail->next = mem_init;
308 tail = mem_init;
309 init_header->size += qat_hal_get_ins_num();
310 mem_val_attr++;
311 }
312 return 0;
313out_err:
314 while (tail_old) {
315 mem_init = tail_old->next;
316 kfree(tail_old);
317 tail_old = mem_init;
318 }
319 if (flag)
320 kfree(*init_tab_base);
321 return -ENOMEM;
322}
323
324static int qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle *handle,
325 struct icp_qat_uof_initmem *init_mem)
326{
327 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
328 unsigned int ae;
329
330 if (qat_uclo_fetch_initmem_ae(handle, init_mem,
331 ICP_QAT_UCLO_MAX_LMEM_REG, &ae))
332 return -EINVAL;
333 if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
Tadeusz Struk45cff262014-07-25 15:55:26 -0700334 &obj_handle->lm_init_tab[ae]))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700335 return -EINVAL;
336 return 0;
337}
338
339static int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
340 struct icp_qat_uof_initmem *init_mem)
341{
342 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
343 unsigned int ae, ustore_size, uaddr, i;
344
345 ustore_size = obj_handle->ustore_phy_size;
346 if (qat_uclo_fetch_initmem_ae(handle, init_mem, ustore_size, &ae))
347 return -EINVAL;
348 if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
Tadeusz Struk45cff262014-07-25 15:55:26 -0700349 &obj_handle->umem_init_tab[ae]))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700350 return -EINVAL;
351 /* set the highest ustore address referenced */
352 uaddr = (init_mem->addr + init_mem->num_in_bytes) >> 0x2;
353 for (i = 0; i < obj_handle->ae_data[ae].slice_num; i++) {
354 if (obj_handle->ae_data[ae].ae_slices[i].
355 encap_image->uwords_num < uaddr)
356 obj_handle->ae_data[ae].ae_slices[i].
357 encap_image->uwords_num = uaddr;
358 }
359 return 0;
360}
361
362#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000
363static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
364 struct icp_qat_uof_initmem *init_mem)
365{
366 unsigned int i;
367 struct icp_qat_uof_memvar_attr *mem_val_attr;
368
369 mem_val_attr =
370 (struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
371 sizeof(struct icp_qat_uof_initmem));
372
373 switch (init_mem->region) {
374 case ICP_QAT_UOF_SRAM_REGION:
375 if ((init_mem->addr + init_mem->num_in_bytes) >
376 ICP_DH895XCC_PESRAM_BAR_SIZE) {
377 pr_err("QAT: initmem on SRAM is out of range");
378 return -EINVAL;
379 }
380 for (i = 0; i < init_mem->val_attr_num; i++) {
381 qat_uclo_wr_sram_by_words(handle,
382 init_mem->addr +
383 mem_val_attr->offset_in_byte,
384 &mem_val_attr->value, 4);
385 mem_val_attr++;
386 }
387 break;
388 case ICP_QAT_UOF_LMEM_REGION:
389 if (qat_uclo_init_lmem_seg(handle, init_mem))
390 return -EINVAL;
391 break;
392 case ICP_QAT_UOF_UMEM_REGION:
393 if (qat_uclo_init_umem_seg(handle, init_mem))
394 return -EINVAL;
395 break;
396 default:
397 pr_err("QAT: initmem region error. region type=0x%x\n",
398 init_mem->region);
399 return -EINVAL;
400 }
401 return 0;
402}
403
404static int qat_uclo_init_ustore(struct icp_qat_fw_loader_handle *handle,
405 struct icp_qat_uclo_encapme *image)
406{
407 unsigned int i;
408 struct icp_qat_uclo_encap_page *page;
409 struct icp_qat_uof_image *uof_image;
410 unsigned char ae;
411 unsigned int ustore_size;
412 unsigned int patt_pos;
413 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
414 uint64_t *fill_data;
415
416 uof_image = image->img_ptr;
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700417 fill_data = kcalloc(ICP_QAT_UCLO_MAX_USTORE, sizeof(uint64_t),
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700418 GFP_KERNEL);
419 if (!fill_data)
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700420 return -ENOMEM;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700421 for (i = 0; i < ICP_QAT_UCLO_MAX_USTORE; i++)
422 memcpy(&fill_data[i], &uof_image->fill_pattern,
423 sizeof(uint64_t));
424 page = image->page;
425
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700426 for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
Tadeusz Struk45cff262014-07-25 15:55:26 -0700427 if (!test_bit(ae, (unsigned long *)&uof_image->ae_assigned))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700428 continue;
429 ustore_size = obj_handle->ae_data[ae].eff_ustore_size;
430 patt_pos = page->beg_addr_p + page->micro_words_num;
431
432 qat_hal_wr_uwords(handle, (unsigned char)ae, 0,
433 page->beg_addr_p, &fill_data[0]);
434 qat_hal_wr_uwords(handle, (unsigned char)ae, patt_pos,
435 ustore_size - patt_pos + 1,
436 &fill_data[page->beg_addr_p]);
437 }
438 kfree(fill_data);
439 return 0;
440}
441
442static int qat_uclo_init_memory(struct icp_qat_fw_loader_handle *handle)
443{
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700444 int i, ae;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700445 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
446 struct icp_qat_uof_initmem *initmem = obj_handle->init_mem_tab.init_mem;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700447
448 for (i = 0; i < obj_handle->init_mem_tab.entry_num; i++) {
449 if (initmem->num_in_bytes) {
450 if (qat_uclo_init_ae_memory(handle, initmem))
451 return -EINVAL;
452 }
453 initmem = (struct icp_qat_uof_initmem *)((unsigned long)(
454 (unsigned long)initmem +
455 sizeof(struct icp_qat_uof_initmem)) +
456 (sizeof(struct icp_qat_uof_memvar_attr) *
457 initmem->val_attr_num));
458 }
459 for (ae = 0; ae < ICP_QAT_UCLO_MAX_AE; ae++) {
460 if (qat_hal_batch_wr_lm(handle, ae,
461 obj_handle->lm_init_tab[ae])) {
462 pr_err("QAT: fail to batch init lmem for AE %d\n", ae);
463 return -EINVAL;
464 }
465 qat_uclo_cleanup_batch_init_list(handle,
466 &obj_handle->lm_init_tab[ae]);
467 qat_uclo_batch_wr_umem(handle, ae,
468 obj_handle->umem_init_tab[ae]);
469 qat_uclo_cleanup_batch_init_list(handle,
470 &obj_handle->
471 umem_init_tab[ae]);
472 }
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700473 return 0;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700474}
475
476static void *qat_uclo_find_chunk(struct icp_qat_uof_objhdr *obj_hdr,
477 char *chunk_id, void *cur)
478{
479 int i;
480 struct icp_qat_uof_chunkhdr *chunk_hdr =
481 (struct icp_qat_uof_chunkhdr *)
482 ((unsigned long)obj_hdr + sizeof(struct icp_qat_uof_objhdr));
483
484 for (i = 0; i < obj_hdr->num_chunks; i++) {
485 if ((cur < (void *)&chunk_hdr[i]) &&
Tadeusz Struk45cff262014-07-25 15:55:26 -0700486 !strncmp(chunk_hdr[i].chunk_id, chunk_id,
487 ICP_QAT_UOF_OBJID_LEN)) {
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700488 return &chunk_hdr[i];
489 }
490 }
491 return NULL;
492}
493
494static unsigned int qat_uclo_calc_checksum(unsigned int reg, int ch)
495{
496 int i;
497 unsigned int topbit = 1 << 0xF;
498 unsigned int inbyte = (unsigned int)((reg >> 0x18) ^ ch);
499
500 reg ^= inbyte << 0x8;
501 for (i = 0; i < 0x8; i++) {
502 if (reg & topbit)
503 reg = (reg << 1) ^ 0x1021;
504 else
505 reg <<= 1;
506 }
507 return reg & 0xFFFF;
508}
509
510static unsigned int qat_uclo_calc_str_checksum(char *ptr, int num)
511{
512 unsigned int chksum = 0;
513
514 if (ptr)
515 while (num--)
516 chksum = qat_uclo_calc_checksum(chksum, *ptr++);
517 return chksum;
518}
519
520static struct icp_qat_uclo_objhdr *
521qat_uclo_map_chunk(char *buf, struct icp_qat_uof_filehdr *file_hdr,
522 char *chunk_id)
523{
524 struct icp_qat_uof_filechunkhdr *file_chunk;
525 struct icp_qat_uclo_objhdr *obj_hdr;
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700526 char *chunk;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700527 int i;
528
529 file_chunk = (struct icp_qat_uof_filechunkhdr *)
530 (buf + sizeof(struct icp_qat_uof_filehdr));
531 for (i = 0; i < file_hdr->num_chunks; i++) {
Tadeusz Struk45cff262014-07-25 15:55:26 -0700532 if (!strncmp(file_chunk->chunk_id, chunk_id,
533 ICP_QAT_UOF_OBJID_LEN)) {
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700534 chunk = buf + file_chunk->offset;
535 if (file_chunk->checksum != qat_uclo_calc_str_checksum(
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700536 chunk, file_chunk->size))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700537 break;
538 obj_hdr = kzalloc(sizeof(*obj_hdr), GFP_KERNEL);
539 if (!obj_hdr)
540 break;
541 obj_hdr->file_buff = chunk;
542 obj_hdr->checksum = file_chunk->checksum;
543 obj_hdr->size = file_chunk->size;
544 return obj_hdr;
545 }
546 file_chunk++;
547 }
548 return NULL;
549}
550
551static unsigned int
552qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj,
553 struct icp_qat_uof_image *image)
554{
555 struct icp_qat_uof_objtable *uc_var_tab, *imp_var_tab, *imp_expr_tab;
556 struct icp_qat_uof_objtable *neigh_reg_tab;
557 struct icp_qat_uof_code_page *code_page;
558
559 code_page = (struct icp_qat_uof_code_page *)
560 ((char *)image + sizeof(struct icp_qat_uof_image));
561 uc_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
562 code_page->uc_var_tab_offset);
563 imp_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
564 code_page->imp_var_tab_offset);
565 imp_expr_tab = (struct icp_qat_uof_objtable *)
566 (encap_uof_obj->beg_uof +
567 code_page->imp_expr_tab_offset);
568 if (uc_var_tab->entry_num || imp_var_tab->entry_num ||
569 imp_expr_tab->entry_num) {
570 pr_err("QAT: UOF can't contain imported variable to be parsed");
571 return -EINVAL;
572 }
573 neigh_reg_tab = (struct icp_qat_uof_objtable *)
574 (encap_uof_obj->beg_uof +
575 code_page->neigh_reg_tab_offset);
576 if (neigh_reg_tab->entry_num) {
577 pr_err("QAT: UOF can't contain shared control store feature");
578 return -EINVAL;
579 }
580 if (image->numpages > 1) {
581 pr_err("QAT: UOF can't contain multiple pages");
582 return -EINVAL;
583 }
584 if (ICP_QAT_SHARED_USTORE_MODE(image->ae_mode)) {
585 pr_err("QAT: UOF can't use shared control store feature");
586 return -EFAULT;
587 }
588 if (RELOADABLE_CTX_SHARED_MODE(image->ae_mode)) {
589 pr_err("QAT: UOF can't use reloadable feature");
590 return -EFAULT;
591 }
592 return 0;
593}
594
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700595static void qat_uclo_map_image_page(struct icp_qat_uof_encap_obj
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700596 *encap_uof_obj,
597 struct icp_qat_uof_image *img,
598 struct icp_qat_uclo_encap_page *page)
599{
600 struct icp_qat_uof_code_page *code_page;
601 struct icp_qat_uof_code_area *code_area;
602 struct icp_qat_uof_objtable *uword_block_tab;
603 struct icp_qat_uof_uword_block *uwblock;
604 int i;
605
606 code_page = (struct icp_qat_uof_code_page *)
607 ((char *)img + sizeof(struct icp_qat_uof_image));
608 page->def_page = code_page->def_page;
609 page->page_region = code_page->page_region;
610 page->beg_addr_v = code_page->beg_addr_v;
611 page->beg_addr_p = code_page->beg_addr_p;
612 code_area = (struct icp_qat_uof_code_area *)(encap_uof_obj->beg_uof +
613 code_page->code_area_offset);
614 page->micro_words_num = code_area->micro_words_num;
615 uword_block_tab = (struct icp_qat_uof_objtable *)
616 (encap_uof_obj->beg_uof +
617 code_area->uword_block_tab);
618 page->uwblock_num = uword_block_tab->entry_num;
619 uwblock = (struct icp_qat_uof_uword_block *)((char *)uword_block_tab +
620 sizeof(struct icp_qat_uof_objtable));
621 page->uwblock = (struct icp_qat_uclo_encap_uwblock *)uwblock;
622 for (i = 0; i < uword_block_tab->entry_num; i++)
623 page->uwblock[i].micro_words =
624 (unsigned long)encap_uof_obj->beg_uof + uwblock[i].uword_offset;
625}
626
627static int qat_uclo_map_uimage(struct icp_qat_uclo_objhandle *obj_handle,
628 struct icp_qat_uclo_encapme *ae_uimage,
629 int max_image)
630{
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700631 int i, j;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700632 struct icp_qat_uof_chunkhdr *chunk_hdr = NULL;
633 struct icp_qat_uof_image *image;
634 struct icp_qat_uof_objtable *ae_regtab;
635 struct icp_qat_uof_objtable *init_reg_sym_tab;
636 struct icp_qat_uof_objtable *sbreak_tab;
637 struct icp_qat_uof_encap_obj *encap_uof_obj =
638 &obj_handle->encap_uof_obj;
639
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700640 for (j = 0; j < max_image; j++) {
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700641 chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
642 ICP_QAT_UOF_IMAG, chunk_hdr);
643 if (!chunk_hdr)
644 break;
645 image = (struct icp_qat_uof_image *)(encap_uof_obj->beg_uof +
646 chunk_hdr->offset);
647 ae_regtab = (struct icp_qat_uof_objtable *)
648 (image->reg_tab_offset +
649 obj_handle->obj_hdr->file_buff);
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700650 ae_uimage[j].ae_reg_num = ae_regtab->entry_num;
651 ae_uimage[j].ae_reg = (struct icp_qat_uof_ae_reg *)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700652 (((char *)ae_regtab) +
653 sizeof(struct icp_qat_uof_objtable));
654 init_reg_sym_tab = (struct icp_qat_uof_objtable *)
655 (image->init_reg_sym_tab +
656 obj_handle->obj_hdr->file_buff);
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700657 ae_uimage[j].init_regsym_num = init_reg_sym_tab->entry_num;
658 ae_uimage[j].init_regsym = (struct icp_qat_uof_init_regsym *)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700659 (((char *)init_reg_sym_tab) +
660 sizeof(struct icp_qat_uof_objtable));
661 sbreak_tab = (struct icp_qat_uof_objtable *)
662 (image->sbreak_tab + obj_handle->obj_hdr->file_buff);
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700663 ae_uimage[j].sbreak_num = sbreak_tab->entry_num;
664 ae_uimage[j].sbreak = (struct icp_qat_uof_sbreak *)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700665 (((char *)sbreak_tab) +
666 sizeof(struct icp_qat_uof_objtable));
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700667 ae_uimage[j].img_ptr = image;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700668 if (qat_uclo_check_image_compat(encap_uof_obj, image))
669 goto out_err;
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700670 ae_uimage[j].page =
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700671 kzalloc(sizeof(struct icp_qat_uclo_encap_page),
672 GFP_KERNEL);
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700673 if (!ae_uimage[j].page)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700674 goto out_err;
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700675 qat_uclo_map_image_page(encap_uof_obj, image,
676 ae_uimage[j].page);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700677 }
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700678 return j;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700679out_err:
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700680 for (i = 0; i < j; i++)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700681 kfree(ae_uimage[i].page);
682 return 0;
683}
684
685static int qat_uclo_map_ae(struct icp_qat_fw_loader_handle *handle, int max_ae)
686{
687 int i, ae;
688 int mflag = 0;
689 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
690
691 for (ae = 0; ae <= max_ae; ae++) {
Tadeusz Struk45cff262014-07-25 15:55:26 -0700692 if (!test_bit(ae,
693 (unsigned long *)&handle->hal_handle->ae_mask))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700694 continue;
695 for (i = 0; i < obj_handle->uimage_num; i++) {
696 if (!test_bit(ae, (unsigned long *)
Tadeusz Struk45cff262014-07-25 15:55:26 -0700697 &obj_handle->ae_uimage[i].img_ptr->ae_assigned))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700698 continue;
699 mflag = 1;
700 if (qat_uclo_init_ae_data(obj_handle, ae, i))
701 return -EINVAL;
702 }
703 }
704 if (!mflag) {
705 pr_err("QAT: uimage uses AE not set");
706 return -EINVAL;
707 }
708 return 0;
709}
710
711static struct icp_qat_uof_strtable *
712qat_uclo_map_str_table(struct icp_qat_uclo_objhdr *obj_hdr,
713 char *tab_name, struct icp_qat_uof_strtable *str_table)
714{
715 struct icp_qat_uof_chunkhdr *chunk_hdr;
716
717 chunk_hdr = qat_uclo_find_chunk((struct icp_qat_uof_objhdr *)
718 obj_hdr->file_buff, tab_name, NULL);
719 if (chunk_hdr) {
720 int hdr_size;
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700721
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700722 memcpy(&str_table->table_len, obj_hdr->file_buff +
723 chunk_hdr->offset, sizeof(str_table->table_len));
724 hdr_size = (char *)&str_table->strings - (char *)str_table;
725 str_table->strings = (unsigned long)obj_hdr->file_buff +
726 chunk_hdr->offset + hdr_size;
727 return str_table;
728 }
729 return NULL;
730}
731
732static void
733qat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj *encap_uof_obj,
734 struct icp_qat_uclo_init_mem_table *init_mem_tab)
735{
736 struct icp_qat_uof_chunkhdr *chunk_hdr;
737
738 chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
739 ICP_QAT_UOF_IMEM, NULL);
740 if (chunk_hdr) {
741 memmove(&init_mem_tab->entry_num, encap_uof_obj->beg_uof +
742 chunk_hdr->offset, sizeof(unsigned int));
743 init_mem_tab->init_mem = (struct icp_qat_uof_initmem *)
744 (encap_uof_obj->beg_uof + chunk_hdr->offset +
745 sizeof(unsigned int));
746 }
747}
748
749static int qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle *obj_handle)
750{
751 unsigned int maj_ver, prod_type = obj_handle->prod_type;
752
753 if (!(prod_type & obj_handle->encap_uof_obj.obj_hdr->cpu_type)) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700754 pr_err("QAT: UOF type 0x%x not match with cur platform 0x%x\n",
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700755 obj_handle->encap_uof_obj.obj_hdr->cpu_type, prod_type);
756 return -EINVAL;
757 }
758 maj_ver = obj_handle->prod_rev & 0xff;
759 if ((obj_handle->encap_uof_obj.obj_hdr->max_cpu_ver < maj_ver) ||
760 (obj_handle->encap_uof_obj.obj_hdr->min_cpu_ver > maj_ver)) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700761 pr_err("QAT: UOF majVer 0x%x out of range\n", maj_ver);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700762 return -EINVAL;
763 }
764 return 0;
765}
766
767static int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle,
768 unsigned char ae, unsigned char ctx_mask,
769 enum icp_qat_uof_regtype reg_type,
770 unsigned short reg_addr, unsigned int value)
771{
772 switch (reg_type) {
773 case ICP_GPA_ABS:
774 case ICP_GPB_ABS:
775 ctx_mask = 0;
776 case ICP_GPA_REL:
777 case ICP_GPB_REL:
778 return qat_hal_init_gpr(handle, ae, ctx_mask, reg_type,
779 reg_addr, value);
780 case ICP_SR_ABS:
781 case ICP_DR_ABS:
782 case ICP_SR_RD_ABS:
783 case ICP_DR_RD_ABS:
784 ctx_mask = 0;
785 case ICP_SR_REL:
786 case ICP_DR_REL:
787 case ICP_SR_RD_REL:
788 case ICP_DR_RD_REL:
789 return qat_hal_init_rd_xfer(handle, ae, ctx_mask, reg_type,
790 reg_addr, value);
791 case ICP_SR_WR_ABS:
792 case ICP_DR_WR_ABS:
793 ctx_mask = 0;
794 case ICP_SR_WR_REL:
795 case ICP_DR_WR_REL:
796 return qat_hal_init_wr_xfer(handle, ae, ctx_mask, reg_type,
797 reg_addr, value);
798 case ICP_NEIGH_REL:
799 return qat_hal_init_nn(handle, ae, ctx_mask, reg_addr, value);
800 default:
801 pr_err("QAT: UOF uses not supported reg type 0x%x\n", reg_type);
802 return -EFAULT;
803 }
804 return 0;
805}
806
807static int qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle *handle,
808 unsigned int ae,
809 struct icp_qat_uclo_encapme *encap_ae)
810{
811 unsigned int i;
812 unsigned char ctx_mask;
813 struct icp_qat_uof_init_regsym *init_regsym;
814
815 if (ICP_QAT_CTX_MODE(encap_ae->img_ptr->ae_mode) ==
816 ICP_QAT_UCLO_MAX_CTX)
817 ctx_mask = 0xff;
818 else
819 ctx_mask = 0x55;
820
821 for (i = 0; i < encap_ae->init_regsym_num; i++) {
822 unsigned int exp_res;
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700823
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700824 init_regsym = &encap_ae->init_regsym[i];
825 exp_res = init_regsym->value;
826 switch (init_regsym->init_type) {
827 case ICP_QAT_UOF_INIT_REG:
828 qat_uclo_init_reg(handle, ae, ctx_mask,
829 (enum icp_qat_uof_regtype)
830 init_regsym->reg_type,
831 (unsigned short)init_regsym->reg_addr,
832 exp_res);
833 break;
834 case ICP_QAT_UOF_INIT_REG_CTX:
835 /* check if ctx is appropriate for the ctxMode */
836 if (!((1 << init_regsym->ctx) & ctx_mask)) {
837 pr_err("QAT: invalid ctx num = 0x%x\n",
838 init_regsym->ctx);
839 return -EINVAL;
840 }
841 qat_uclo_init_reg(handle, ae,
842 (unsigned char)
843 (1 << init_regsym->ctx),
844 (enum icp_qat_uof_regtype)
845 init_regsym->reg_type,
846 (unsigned short)init_regsym->reg_addr,
847 exp_res);
848 break;
849 case ICP_QAT_UOF_INIT_EXPR:
850 pr_err("QAT: INIT_EXPR feature not supported\n");
851 return -EINVAL;
852 case ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP:
853 pr_err("QAT: INIT_EXPR_ENDIAN_SWAP feature not supported\n");
854 return -EINVAL;
855 default:
856 break;
857 }
858 }
859 return 0;
860}
861
862static int qat_uclo_init_globals(struct icp_qat_fw_loader_handle *handle)
863{
864 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
865 unsigned int s, ae;
866
867 if (obj_handle->global_inited)
868 return 0;
869 if (obj_handle->init_mem_tab.entry_num) {
870 if (qat_uclo_init_memory(handle)) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700871 pr_err("QAT: initialize memory failed\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700872 return -EINVAL;
873 }
874 }
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700875 for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700876 for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
877 if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
878 continue;
879 if (qat_uclo_init_reg_sym(handle, ae,
880 obj_handle->ae_data[ae].
881 ae_slices[s].encap_image))
882 return -EINVAL;
883 }
884 }
885 obj_handle->global_inited = 1;
886 return 0;
887}
888
889static int qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle *handle)
890{
891 unsigned char ae, nn_mode, s;
892 struct icp_qat_uof_image *uof_image;
893 struct icp_qat_uclo_aedata *ae_data;
894 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
895
Tadeusz Struk9a147cb2014-07-25 15:55:46 -0700896 for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700897 if (!test_bit(ae,
Tadeusz Struk45cff262014-07-25 15:55:26 -0700898 (unsigned long *)&handle->hal_handle->ae_mask))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700899 continue;
Tadeusz Struk45cff262014-07-25 15:55:26 -0700900 ae_data = &obj_handle->ae_data[ae];
Tadeusz Strukdf0088f2014-07-25 15:55:32 -0700901 for (s = 0; s < min_t(unsigned int, ae_data->slice_num,
902 ICP_QAT_UCLO_MAX_CTX); s++) {
Tadeusz Struk45cff262014-07-25 15:55:26 -0700903 if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700904 continue;
905 uof_image = ae_data->ae_slices[s].encap_image->img_ptr;
906 if (qat_hal_set_ae_ctx_mode(handle, ae,
907 (char)ICP_QAT_CTX_MODE
908 (uof_image->ae_mode))) {
909 pr_err("QAT: qat_hal_set_ae_ctx_mode error\n");
910 return -EFAULT;
911 }
912 nn_mode = ICP_QAT_NN_MODE(uof_image->ae_mode);
913 if (qat_hal_set_ae_nn_mode(handle, ae, nn_mode)) {
914 pr_err("QAT: qat_hal_set_ae_nn_mode error\n");
915 return -EFAULT;
916 }
917 if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM0,
918 (char)ICP_QAT_LOC_MEM0_MODE
919 (uof_image->ae_mode))) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700920 pr_err("QAT: qat_hal_set_ae_lm_mode LMEM0 error\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700921 return -EFAULT;
922 }
923 if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM1,
924 (char)ICP_QAT_LOC_MEM1_MODE
925 (uof_image->ae_mode))) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700926 pr_err("QAT: qat_hal_set_ae_lm_mode LMEM1 error\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700927 return -EFAULT;
928 }
929 }
930 }
931 return 0;
932}
933
934static void qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle *handle)
935{
936 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
937 struct icp_qat_uclo_encapme *image;
938 int a;
939
940 for (a = 0; a < obj_handle->uimage_num; a++) {
941 image = &obj_handle->ae_uimage[a];
942 image->uwords_num = image->page->beg_addr_p +
943 image->page->micro_words_num;
944 }
945}
946
947static int qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle *handle)
948{
949 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
950 unsigned int ae;
951
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700952 obj_handle->uword_buf = kcalloc(UWORD_CPYBUF_SIZE, sizeof(uint64_t),
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700953 GFP_KERNEL);
954 if (!obj_handle->uword_buf)
955 return -ENOMEM;
956 obj_handle->encap_uof_obj.beg_uof = obj_handle->obj_hdr->file_buff;
957 obj_handle->encap_uof_obj.obj_hdr = (struct icp_qat_uof_objhdr *)
958 obj_handle->obj_hdr->file_buff;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700959 obj_handle->uword_in_bytes = 6;
960 obj_handle->prod_type = ICP_QAT_AC_C_CPU_TYPE;
961 obj_handle->prod_rev = PID_MAJOR_REV |
962 (PID_MINOR_REV & handle->hal_handle->revision_id);
963 if (qat_uclo_check_uof_compat(obj_handle)) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700964 pr_err("QAT: UOF incompatible\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700965 return -EINVAL;
966 }
967 obj_handle->ustore_phy_size = ICP_QAT_UCLO_MAX_USTORE;
Tadeusz Struk45cff262014-07-25 15:55:26 -0700968 if (!obj_handle->obj_hdr->file_buff ||
969 !qat_uclo_map_str_table(obj_handle->obj_hdr, ICP_QAT_UOF_STRT,
970 &obj_handle->str_table)) {
Tadeusz Struk68991722014-07-25 15:55:52 -0700971 pr_err("QAT: UOF doesn't have effective images\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700972 goto out_err;
973 }
974 obj_handle->uimage_num =
975 qat_uclo_map_uimage(obj_handle, obj_handle->ae_uimage,
976 ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX);
977 if (!obj_handle->uimage_num)
978 goto out_err;
979 if (qat_uclo_map_ae(handle, handle->hal_handle->ae_max_num)) {
Tadeusz Strukd65071e2014-06-24 15:19:34 -0700980 pr_err("QAT: Bad object\n");
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700981 goto out_check_uof_aemask_err;
982 }
983 qat_uclo_init_uword_num(handle);
Tadeusz Struk45cff262014-07-25 15:55:26 -0700984 qat_uclo_map_initmem_table(&obj_handle->encap_uof_obj,
985 &obj_handle->init_mem_tab);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -0700986 if (qat_uclo_set_ae_mode(handle))
987 goto out_check_uof_aemask_err;
988 return 0;
989out_check_uof_aemask_err:
990 for (ae = 0; ae < obj_handle->uimage_num; ae++)
991 kfree(obj_handle->ae_uimage[ae].page);
992out_err:
993 kfree(obj_handle->uword_buf);
994 return -EFAULT;
995}
996
997int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
998 void *addr_ptr, int mem_size)
999{
1000 struct icp_qat_uof_filehdr *filehdr;
1001 struct icp_qat_uclo_objhandle *objhdl;
1002
1003 BUILD_BUG_ON(ICP_QAT_UCLO_MAX_AE >=
1004 (sizeof(handle->hal_handle->ae_mask) * 8));
1005
1006 if (!handle || !addr_ptr || mem_size < 24)
1007 return -EINVAL;
1008 objhdl = kzalloc(sizeof(*objhdl), GFP_KERNEL);
1009 if (!objhdl)
1010 return -ENOMEM;
1011 objhdl->obj_buf = kmemdup(addr_ptr, mem_size, GFP_KERNEL);
1012 if (!objhdl->obj_buf)
1013 goto out_objbuf_err;
1014 filehdr = (struct icp_qat_uof_filehdr *)objhdl->obj_buf;
1015 if (qat_uclo_check_format(filehdr))
1016 goto out_objhdr_err;
1017 objhdl->obj_hdr = qat_uclo_map_chunk((char *)objhdl->obj_buf, filehdr,
1018 ICP_QAT_UOF_OBJS);
1019 if (!objhdl->obj_hdr) {
1020 pr_err("QAT: object file chunk is null\n");
1021 goto out_objhdr_err;
1022 }
1023 handle->obj_handle = objhdl;
1024 if (qat_uclo_parse_uof_obj(handle))
1025 goto out_overlay_obj_err;
1026 return 0;
1027
1028out_overlay_obj_err:
1029 handle->obj_handle = NULL;
1030 kfree(objhdl->obj_hdr);
1031out_objhdr_err:
1032 kfree(objhdl->obj_buf);
1033out_objbuf_err:
1034 kfree(objhdl);
1035 return -ENOMEM;
1036}
1037
Tadeusz Struk8f312d62014-06-24 15:19:40 -07001038void qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001039{
1040 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
Tadeusz Struk9a147cb2014-07-25 15:55:46 -07001041 unsigned int a;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001042
Tadeusz Struk8f312d62014-06-24 15:19:40 -07001043 if (!obj_handle)
1044 return;
1045
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001046 kfree(obj_handle->uword_buf);
1047 for (a = 0; a < obj_handle->uimage_num; a++)
1048 kfree(obj_handle->ae_uimage[a].page);
1049
Tadeusz Struk9a147cb2014-07-25 15:55:46 -07001050 for (a = 0; a < handle->hal_handle->ae_max_num; a++)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001051 qat_uclo_free_ae_data(&obj_handle->ae_data[a]);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001052
Tadeusz Struk8f312d62014-06-24 15:19:40 -07001053 kfree(obj_handle->obj_hdr);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001054 kfree(obj_handle->obj_buf);
1055 kfree(obj_handle);
1056 handle->obj_handle = NULL;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001057}
1058
1059static void qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle *obj_handle,
1060 struct icp_qat_uclo_encap_page *encap_page,
1061 uint64_t *uword, unsigned int addr_p,
1062 unsigned int raddr, uint64_t fill)
1063{
1064 uint64_t uwrd = 0;
1065 unsigned int i;
1066
1067 if (!encap_page) {
1068 *uword = fill;
1069 return;
1070 }
1071 for (i = 0; i < encap_page->uwblock_num; i++) {
1072 if (raddr >= encap_page->uwblock[i].start_addr &&
1073 raddr <= encap_page->uwblock[i].start_addr +
1074 encap_page->uwblock[i].words_num - 1) {
1075 raddr -= encap_page->uwblock[i].start_addr;
1076 raddr *= obj_handle->uword_in_bytes;
1077 memcpy(&uwrd, (void *)(((unsigned long)
1078 encap_page->uwblock[i].micro_words) + raddr),
1079 obj_handle->uword_in_bytes);
1080 uwrd = uwrd & 0xbffffffffffull;
1081 }
1082 }
1083 *uword = uwrd;
1084 if (*uword == INVLD_UWORD)
1085 *uword = fill;
1086}
1087
Tadeusz Struk341b2a32014-07-25 15:55:09 -07001088static void qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle,
1089 struct icp_qat_uclo_encap_page
1090 *encap_page, unsigned int ae)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001091{
1092 unsigned int uw_physical_addr, uw_relative_addr, i, words_num, cpylen;
1093 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
1094 uint64_t fill_pat;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001095
1096 /* load the page starting at appropriate ustore address */
1097 /* get fill-pattern from an image -- they are all the same */
1098 memcpy(&fill_pat, obj_handle->ae_uimage[0].img_ptr->fill_pattern,
1099 sizeof(uint64_t));
1100 uw_physical_addr = encap_page->beg_addr_p;
1101 uw_relative_addr = 0;
1102 words_num = encap_page->micro_words_num;
1103 while (words_num) {
1104 if (words_num < UWORD_CPYBUF_SIZE)
1105 cpylen = words_num;
1106 else
1107 cpylen = UWORD_CPYBUF_SIZE;
1108
1109 /* load the buffer */
1110 for (i = 0; i < cpylen; i++)
1111 qat_uclo_fill_uwords(obj_handle, encap_page,
1112 &obj_handle->uword_buf[i],
1113 uw_physical_addr + i,
1114 uw_relative_addr + i, fill_pat);
1115
1116 /* copy the buffer to ustore */
1117 qat_hal_wr_uwords(handle, (unsigned char)ae,
1118 uw_physical_addr, cpylen,
1119 obj_handle->uword_buf);
1120
1121 uw_physical_addr += cpylen;
1122 uw_relative_addr += cpylen;
1123 words_num -= cpylen;
1124 }
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001125}
1126
Tadeusz Struk9a147cb2014-07-25 15:55:46 -07001127static void qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle *handle,
1128 struct icp_qat_uof_image *image)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001129{
1130 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
1131 unsigned int ctx_mask, s;
1132 struct icp_qat_uclo_page *page;
1133 unsigned char ae;
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001134 int ctx;
1135
1136 if (ICP_QAT_CTX_MODE(image->ae_mode) == ICP_QAT_UCLO_MAX_CTX)
1137 ctx_mask = 0xff;
1138 else
1139 ctx_mask = 0x55;
1140 /* load the default page and set assigned CTX PC
1141 * to the entrypoint address */
Tadeusz Struk9a147cb2014-07-25 15:55:46 -07001142 for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
Tadeusz Struk45cff262014-07-25 15:55:26 -07001143 if (!test_bit(ae, (unsigned long *)&image->ae_assigned))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001144 continue;
1145 /* find the slice to which this image is assigned */
1146 for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
1147 if (image->ctx_assigned & obj_handle->ae_data[ae].
1148 ae_slices[s].ctx_mask_assigned)
1149 break;
1150 }
1151 if (s >= obj_handle->ae_data[ae].slice_num)
1152 continue;
1153 page = obj_handle->ae_data[ae].ae_slices[s].page;
1154 if (!page->encap_page->def_page)
1155 continue;
Tadeusz Struk341b2a32014-07-25 15:55:09 -07001156 qat_uclo_wr_uimage_raw_page(handle, page->encap_page, ae);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001157
1158 page = obj_handle->ae_data[ae].ae_slices[s].page;
1159 for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++)
1160 obj_handle->ae_data[ae].ae_slices[s].cur_page[ctx] =
1161 (ctx_mask & (1 << ctx)) ? page : NULL;
1162 qat_hal_set_live_ctx(handle, (unsigned char)ae,
1163 image->ctx_assigned);
1164 qat_hal_set_pc(handle, (unsigned char)ae, image->ctx_assigned,
1165 image->entry_address);
1166 }
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001167}
1168
1169int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle)
1170{
1171 struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
1172 unsigned int i;
1173
1174 if (qat_uclo_init_globals(handle))
1175 return -EINVAL;
1176 for (i = 0; i < obj_handle->uimage_num; i++) {
Tadeusz Struk45cff262014-07-25 15:55:26 -07001177 if (!obj_handle->ae_uimage[i].img_ptr)
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001178 return -EINVAL;
Tadeusz Struk45cff262014-07-25 15:55:26 -07001179 if (qat_uclo_init_ustore(handle, &obj_handle->ae_uimage[i]))
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001180 return -EINVAL;
Tadeusz Struk9a147cb2014-07-25 15:55:46 -07001181 qat_uclo_wr_uimage_page(handle,
1182 obj_handle->ae_uimage[i].img_ptr);
Tadeusz Strukb4b7e672014-06-05 13:43:47 -07001183 }
1184 return 0;
1185}