From c22487b828adf09a6ffa3cdf47836d7b4407f827 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristina=20Mart=C5=A1enko?= Date: Sun, 27 Jul 2014 22:59:50 +0300 Subject: [PATCH] staging: sep: remove driver MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Looks like no one's working on the driver anymore, so remove it for now. If someone wants to work on moving it out of staging, this commit can be reverted. Signed-off-by: Kristina MartÅ¡enko Cc: Alan Cox Cc: Mark A. Allyn Cc: Jayant Mangalampalli Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/sep/Kconfig | 11 - drivers/staging/sep/Makefile | 3 - drivers/staging/sep/TODO | 3 - drivers/staging/sep/sep_crypto.c | 3979 ------------------- drivers/staging/sep/sep_crypto.h | 359 -- drivers/staging/sep/sep_dev.h | 162 - drivers/staging/sep/sep_driver_api.h | 402 -- drivers/staging/sep/sep_driver_config.h | 298 -- drivers/staging/sep/sep_driver_hw_defs.h | 56 - drivers/staging/sep/sep_main.c | 4411 ---------------------- drivers/staging/sep/sep_trace_events.h | 193 - 13 files changed, 9880 deletions(-) delete mode 100644 drivers/staging/sep/Kconfig delete mode 100644 drivers/staging/sep/Makefile delete mode 100644 drivers/staging/sep/TODO delete mode 100644 drivers/staging/sep/sep_crypto.c delete mode 100644 drivers/staging/sep/sep_crypto.h delete mode 100644 drivers/staging/sep/sep_dev.h delete mode 100644 drivers/staging/sep/sep_driver_api.h delete mode 100644 drivers/staging/sep/sep_driver_config.h delete mode 100644 drivers/staging/sep/sep_driver_hw_defs.h delete mode 100644 drivers/staging/sep/sep_main.c delete mode 100644 drivers/staging/sep/sep_trace_events.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 90624df0db6f..2c486ea6236b 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -64,8 +64,6 @@ source "drivers/staging/vt6655/Kconfig" source "drivers/staging/vt6656/Kconfig" -source "drivers/staging/sep/Kconfig" - source "drivers/staging/iio/Kconfig" source "drivers/staging/xgifb/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 27f44cdde516..1e1a3a10faf7 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_OCTEON_USB) += octeon-usb/ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme/ -obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ diff --git a/drivers/staging/sep/Kconfig b/drivers/staging/sep/Kconfig deleted file mode 100644 index aab945a316ea..000000000000 --- a/drivers/staging/sep/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -config DX_SEP - tristate "Discretix SEP driver" - depends on PCI && CRYPTO - help - Discretix SEP driver; used for the security processor subsystem - on board the Intel Mobile Internet Device and adds SEP availability - to the kernel crypto infrastructure - - The driver's name is sep_driver. - - If unsure, select N. diff --git a/drivers/staging/sep/Makefile b/drivers/staging/sep/Makefile deleted file mode 100644 index e48a7959289e..000000000000 --- a/drivers/staging/sep/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -ccflags-y += -I$(srctree)/$(src) -obj-$(CONFIG_DX_SEP) += sep_driver.o -sep_driver-objs := sep_crypto.o sep_main.o diff --git a/drivers/staging/sep/TODO b/drivers/staging/sep/TODO deleted file mode 100644 index 3524d0cf84ba..000000000000 --- a/drivers/staging/sep/TODO +++ /dev/null @@ -1,3 +0,0 @@ -Todo's so far (from Alan Cox) -- Clean up unused ioctls -- Clean up unused fields in ioctl structures diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c deleted file mode 100644 index 415322867581..000000000000 --- a/drivers/staging/sep/sep_crypto.c +++ /dev/null @@ -1,3979 +0,0 @@ -/* - * - * sep_crypto.c - Crypto interface structures - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2010 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * 2010.09.14 Upgrade to Medfield - * 2011.02.22 Enable Kernel Crypto - * - */ - -/* #define DEBUG */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sep_driver_hw_defs.h" -#include "sep_driver_config.h" -#include "sep_driver_api.h" -#include "sep_dev.h" -#include "sep_crypto.h" - -#if defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) - -/* Globals for queuing */ -static spinlock_t queue_lock; -static struct crypto_queue sep_queue; - -/* Declare of dequeuer */ -static void sep_dequeuer(void *data); - -/* TESTING */ -/** - * sep_do_callback - * @work: pointer to work_struct - * This is what is called by the queue; it is generic so that it - * can be used by any type of operation as each different callback - * function can use the data parameter in its own way - */ -static void sep_do_callback(struct work_struct *work) -{ - struct sep_work_struct *sep_work = container_of(work, - struct sep_work_struct, work); - - if (sep_work != NULL) { - (sep_work->callback)(sep_work->data); - kfree(sep_work); - } else { - pr_debug("sep crypto: do callback - NULL container\n"); - } -} - -/** - * sep_submit_work - * @work_queue: pointer to struct_workqueue - * @funct: pointer to function to execute - * @data: pointer to data; function will know - * how to use it - * This is a generic API to submit something to - * the queue. The callback function will depend - * on what operation is to be done - */ -static int sep_submit_work(struct workqueue_struct *work_queue, - void (*funct)(void *), - void *data) -{ - struct sep_work_struct *sep_work; - int result; - - sep_work = kmalloc(sizeof(struct sep_work_struct), GFP_ATOMIC); - - if (sep_work == NULL) { - pr_debug("sep crypto: cant allocate work structure\n"); - return -ENOMEM; - } - - sep_work->callback = funct; - sep_work->data = data; - INIT_WORK(&sep_work->work, sep_do_callback); - result = queue_work(work_queue, &sep_work->work); - if (!result) { - pr_debug("sep_crypto: queue_work failed\n"); - return -EINVAL; - } - return 0; -} - -/** - * sep_alloc_sg_buf - - * @sep: pointer to struct sep_device - * @size: total size of area - * @block_size: minimum size of chunks - * each page is minimum or modulo this size - * @returns: pointer to struct scatterlist for new - * buffer - **/ -static struct scatterlist *sep_alloc_sg_buf( - struct sep_device *sep, - size_t size, - size_t block_size) -{ - u32 nbr_pages; - u32 ct1; - void *buf; - size_t current_size; - size_t real_page_size; - - struct scatterlist *sg, *sg_temp; - - if (size == 0) - return NULL; - - dev_dbg(&sep->pdev->dev, "sep alloc sg buf\n"); - - current_size = 0; - nbr_pages = 0; - real_page_size = PAGE_SIZE - (PAGE_SIZE % block_size); - /** - * The size of each page must be modulo of the operation - * block size; increment by the modified page size until - * the total size is reached, then you have the number of - * pages - */ - while (current_size < size) { - current_size += real_page_size; - nbr_pages += 1; - } - - sg = kmalloc_array(nbr_pages, sizeof(struct scatterlist), GFP_ATOMIC); - if (!sg) - return NULL; - - sg_init_table(sg, nbr_pages); - - current_size = 0; - sg_temp = sg; - for (ct1 = 0; ct1 < nbr_pages; ct1 += 1) { - buf = (void *)get_zeroed_page(GFP_ATOMIC); - if (!buf) { - dev_warn(&sep->pdev->dev, - "Cannot allocate page for new buffer\n"); - kfree(sg); - return NULL; - } - - sg_set_buf(sg_temp, buf, real_page_size); - if ((size - current_size) > real_page_size) { - sg_temp->length = real_page_size; - current_size += real_page_size; - } else { - sg_temp->length = (size - current_size); - current_size = size; - } - sg_temp = sg_next(sg); - } - return sg; -} - -/** - * sep_free_sg_buf - - * @sg: pointer to struct scatterlist; points to area to free - */ -static void sep_free_sg_buf(struct scatterlist *sg) -{ - struct scatterlist *sg_temp = sg; - while (sg_temp) { - free_page((unsigned long)sg_virt(sg_temp)); - sg_temp = sg_next(sg_temp); - } - kfree(sg); -} - -/** - * sep_copy_sg - - * @sep: pointer to struct sep_device - * @sg_src: pointer to struct scatterlist for source - * @sg_dst: pointer to struct scatterlist for destination - * @size: size (in bytes) of data to copy - * - * Copy data from one scatterlist to another; both must - * be the same size - */ -static void sep_copy_sg( - struct sep_device *sep, - struct scatterlist *sg_src, - struct scatterlist *sg_dst, - size_t size) -{ - u32 seg_size; - u32 in_offset, out_offset; - - u32 count = 0; - struct scatterlist *sg_src_tmp = sg_src; - struct scatterlist *sg_dst_tmp = sg_dst; - - in_offset = 0; - out_offset = 0; - - dev_dbg(&sep->pdev->dev, "sep copy sg\n"); - - if ((sg_src == NULL) || (sg_dst == NULL) || (size == 0)) - return; - - dev_dbg(&sep->pdev->dev, "sep copy sg not null\n"); - - while (count < size) { - if ((sg_src_tmp->length - in_offset) > - (sg_dst_tmp->length - out_offset)) - seg_size = sg_dst_tmp->length - out_offset; - else - seg_size = sg_src_tmp->length - in_offset; - - if (seg_size > (size - count)) - seg_size = (size = count); - - memcpy(sg_virt(sg_dst_tmp) + out_offset, - sg_virt(sg_src_tmp) + in_offset, - seg_size); - - in_offset += seg_size; - out_offset += seg_size; - count += seg_size; - - if (in_offset >= sg_src_tmp->length) { - sg_src_tmp = sg_next(sg_src_tmp); - in_offset = 0; - } - - if (out_offset >= sg_dst_tmp->length) { - sg_dst_tmp = sg_next(sg_dst_tmp); - out_offset = 0; - } - } -} - -/** - * sep_oddball_pages - - * @sep: pointer to struct sep_device - * @sg: pointer to struct scatterlist - buffer to check - * @size: total data size - * @blocksize: minimum block size; must be multiples of this size - * @to_copy: 1 means do copy, 0 means do not copy - * @new_sg: pointer to location to put pointer to new sg area - * @returns: 1 if new scatterlist is needed; 0 if not needed; - * error value if operation failed - * - * The SEP device requires all pages to be multiples of the - * minimum block size appropriate for the operation - * This function check all pages; if any are oddball sizes - * (not multiple of block sizes), it creates a new scatterlist. - * If the to_copy parameter is set to 1, then a scatter list - * copy is performed. The pointer to the new scatterlist is - * put into the address supplied by the new_sg parameter; if - * no new scatterlist is needed, then a NULL is put into - * the location at new_sg. - * - */ -static int sep_oddball_pages( - struct sep_device *sep, - struct scatterlist *sg, - size_t data_size, - u32 block_size, - struct scatterlist **new_sg, - u32 do_copy) -{ - struct scatterlist *sg_temp; - u32 flag; - u32 nbr_pages, page_count; - - dev_dbg(&sep->pdev->dev, "sep oddball\n"); - if ((sg == NULL) || (data_size == 0) || (data_size < block_size)) - return 0; - - dev_dbg(&sep->pdev->dev, "sep oddball not null\n"); - flag = 0; - nbr_pages = 0; - page_count = 0; - sg_temp = sg; - - while (sg_temp) { - nbr_pages += 1; - sg_temp = sg_next(sg_temp); - } - - sg_temp = sg; - while ((sg_temp) && (flag == 0)) { - page_count += 1; - if (sg_temp->length % block_size) - flag = 1; - else - sg_temp = sg_next(sg_temp); - } - - /* Do not process if last (or only) page is oddball */ - if (nbr_pages == page_count) - flag = 0; - - if (flag) { - dev_dbg(&sep->pdev->dev, "sep oddball processing\n"); - *new_sg = sep_alloc_sg_buf(sep, data_size, block_size); - if (*new_sg == NULL) { - dev_warn(&sep->pdev->dev, "cannot allocate new sg\n"); - return -ENOMEM; - } - - if (do_copy) - sep_copy_sg(sep, sg, *new_sg, data_size); - - return 1; - } else { - return 0; - } -} - -/** - * sep_copy_offset_sg - - * @sep: pointer to struct sep_device; - * @sg: pointer to struct scatterlist - * @offset: offset into scatterlist memory - * @dst: place to put data - * @len: length of data - * @returns: number of bytes copies - * - * This copies data from scatterlist buffer - * offset from beginning - it is needed for - * handling tail data in hash - */ -static size_t sep_copy_offset_sg( - struct sep_device *sep, - struct scatterlist *sg, - u32 offset, - void *dst, - u32 len) -{ - size_t page_start; - size_t page_end; - size_t offset_within_page; - size_t length_within_page; - size_t length_remaining; - size_t current_offset; - - /* Find which page is beginning of segment */ - page_start = 0; - page_end = sg->length; - while ((sg) && (offset > page_end)) { - page_start += sg->length; - sg = sg_next(sg); - if (sg) - page_end += sg->length; - } - - if (sg == NULL) - return -ENOMEM; - - offset_within_page = offset - page_start; - if ((sg->length - offset_within_page) >= len) { - /* All within this page */ - memcpy(dst, sg_virt(sg) + offset_within_page, len); - return len; - } else { - /* Scattered multiple pages */ - current_offset = 0; - length_remaining = len; - while ((sg) && (current_offset < len)) { - length_within_page = sg->length - offset_within_page; - if (length_within_page >= length_remaining) { - memcpy(dst+current_offset, - sg_virt(sg) + offset_within_page, - length_remaining); - length_remaining = 0; - current_offset = len; - } else { - memcpy(dst+current_offset, - sg_virt(sg) + offset_within_page, - length_within_page); - length_remaining -= length_within_page; - current_offset += length_within_page; - offset_within_page = 0; - sg = sg_next(sg); - } - } - - if (sg == NULL) - return -ENOMEM; - } - return len; -} - -/** - * partial_overlap - - * @src_ptr: source pointer - * @dst_ptr: destination pointer - * @nbytes: number of bytes - * @returns: 0 for success; -1 for failure - * We cannot have any partial overlap. Total overlap - * where src is the same as dst is okay - */ -static int partial_overlap(void *src_ptr, void *dst_ptr, u32 nbytes) -{ - /* Check for partial overlap */ - if (src_ptr != dst_ptr) { - if (src_ptr < dst_ptr) { - if ((src_ptr + nbytes) > dst_ptr) - return -EINVAL; - } else { - if ((dst_ptr + nbytes) > src_ptr) - return -EINVAL; - } - } - - return 0; -} - -/* Debug - prints only if DEBUG is defined */ -static void sep_dump_ivs(struct ablkcipher_request *req, char *reason) - - { - unsigned char *cptr; - struct sep_aes_internal_context *aes_internal; - struct sep_des_internal_context *des_internal; - int ct1; - - struct this_task_ctx *ta_ctx; - struct crypto_ablkcipher *tfm; - struct sep_system_ctx *sctx; - - ta_ctx = ablkcipher_request_ctx(req); - tfm = crypto_ablkcipher_reqtfm(req); - sctx = crypto_ablkcipher_ctx(tfm); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, "IV DUMP - %s\n", reason); - if ((ta_ctx->current_request == DES_CBC) && - (ta_ctx->des_opmode == SEP_DES_CBC)) { - - des_internal = (struct sep_des_internal_context *) - sctx->des_private_ctx.ctx_buf; - /* print vendor */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep - vendor iv for DES\n"); - cptr = (unsigned char *)des_internal->iv_context; - for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "%02x\n", *(cptr + ct1)); - - /* print walk */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep - walk from kernel crypto iv for DES\n"); - cptr = (unsigned char *)ta_ctx->walk.iv; - for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "%02x\n", *(cptr + ct1)); - } else if ((ta_ctx->current_request == AES_CBC) && - (ta_ctx->aes_opmode == SEP_AES_CBC)) { - - aes_internal = (struct sep_aes_internal_context *) - sctx->aes_private_ctx.cbuff; - /* print vendor */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep - vendor iv for AES\n"); - cptr = (unsigned char *)aes_internal->aes_ctx_iv; - for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "%02x\n", *(cptr + ct1)); - - /* print walk */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep - walk from kernel crypto iv for AES\n"); - cptr = (unsigned char *)ta_ctx->walk.iv; - for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "%02x\n", *(cptr + ct1)); - } -} - -/** - * RFC2451: Weak key check - * Returns: 1 (weak), 0 (not weak) - */ -static int sep_weak_key(const u8 *key, unsigned int keylen) -{ - static const u8 parity[] = { - 8, 1, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 2, 8, - 0, 8, 8, 0, 8, 0, 0, 8, 8, - 0, 0, 8, 0, 8, 8, 3, - 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, - 8, 0, 0, 8, 0, 8, 8, 0, 0, - 8, 8, 0, 8, 0, 0, 8, - 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, - 8, 0, 0, 8, 0, 8, 8, 0, 0, - 8, 8, 0, 8, 0, 0, 8, - 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, - 0, 8, 8, 0, 8, 0, 0, 8, 8, - 0, 0, 8, 0, 8, 8, 0, - 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, - 8, 0, 0, 8, 0, 8, 8, 0, 0, - 8, 8, 0, 8, 0, 0, 8, - 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, - 0, 8, 8, 0, 8, 0, 0, 8, 8, - 0, 0, 8, 0, 8, 8, 0, - 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, - 0, 8, 8, 0, 8, 0, 0, 8, 8, - 0, 0, 8, 0, 8, 8, 0, - 4, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, - 8, 5, 0, 8, 0, 8, 8, 0, 0, - 8, 8, 0, 8, 0, 6, 8, - }; - - u32 n, w; - - n = parity[key[0]]; n <<= 4; - n |= parity[key[1]]; n <<= 4; - n |= parity[key[2]]; n <<= 4; - n |= parity[key[3]]; n <<= 4; - n |= parity[key[4]]; n <<= 4; - n |= parity[key[5]]; n <<= 4; - n |= parity[key[6]]; n <<= 4; - n |= parity[key[7]]; - w = 0x88888888L; - - /* 1 in 10^10 keys passes this test */ - if (!((n - (w >> 3)) & w)) { - if (n < 0x41415151) { - if (n < 0x31312121) { - if (n < 0x14141515) { - /* 01 01 01 01 01 01 01 01 */ - if (n == 0x11111111) - goto weak; - /* 01 1F 01 1F 01 0E 01 0E */ - if (n == 0x13131212) - goto weak; - } else { - /* 01 E0 01 E0 01 F1 01 F1 */ - if (n == 0x14141515) - goto weak; - /* 01 FE 01 FE 01 FE 01 FE */ - if (n == 0x16161616) - goto weak; - } - } else { - if (n < 0x34342525) { - /* 1F 01 1F 01 0E 01 0E 01 */ - if (n == 0x31312121) - goto weak; - /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */ - if (n == 0x33332222) - goto weak; - } else { - /* 1F E0 1F E0 0E F1 0E F1 */ - if (n == 0x34342525) - goto weak; - /* 1F FE 1F FE 0E FE 0E FE */ - if (n == 0x36362626) - goto weak; - } - } - } else { - if (n < 0x61616161) { - if (n < 0x44445555) { - /* E0 01 E0 01 F1 01 F1 01 */ - if (n == 0x41415151) - goto weak; - /* E0 1F E0 1F F1 0E F1 0E */ - if (n == 0x43435252) - goto weak; - } else { - /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */ - if (n == 0x44445555) - goto weak; - /* E0 FE E0 FE F1 FE F1 FE */ - if (n == 0x46465656) - goto weak; - } - } else { - if (n < 0x64646565) { - /* FE 01 FE 01 FE 01 FE 01 */ - if (n == 0x61616161) - goto weak; - /* FE 1F FE 1F FE 0E FE 0E */ - if (n == 0x63636262) - goto weak; - } else { - /* FE E0 FE E0 FE F1 FE F1 */ - if (n == 0x64646565) - goto weak; - /* FE FE FE FE FE FE FE FE */ - if (n == 0x66666666) - goto weak; - } - } - } - } - return 0; -weak: - return 1; -} -/** - * sep_sg_nents - */ -static u32 sep_sg_nents(struct scatterlist *sg) -{ - u32 ct1 = 0; - - while (sg) { - ct1 += 1; - sg = sg_next(sg); - } - - return ct1; -} - -/** - * sep_start_msg - - * @ta_ctx: pointer to struct this_task_ctx - * @returns: offset to place for the next word in the message - * Set up pointer in message pool for new message - */ -static u32 sep_start_msg(struct this_task_ctx *ta_ctx) -{ - u32 *word_ptr; - - ta_ctx->msg_len_words = 2; - ta_ctx->msgptr = ta_ctx->msg; - memset(ta_ctx->msg, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - ta_ctx->msgptr += sizeof(u32) * 2; - word_ptr = (u32 *)ta_ctx->msgptr; - *word_ptr = SEP_START_MSG_TOKEN; - return sizeof(u32) * 2; -} - -/** - * sep_end_msg - - * @ta_ctx: pointer to struct this_task_ctx - * @messages_offset: current message offset - * Returns: 0 for success; <0 otherwise - * End message; set length and CRC; and - * send interrupt to the SEP - */ -static void sep_end_msg(struct this_task_ctx *ta_ctx, u32 msg_offset) -{ - u32 *word_ptr; - /* Msg size goes into msg after token */ - ta_ctx->msg_len_words = msg_offset / sizeof(u32) + 1; - word_ptr = (u32 *)ta_ctx->msgptr; - word_ptr += 1; - *word_ptr = ta_ctx->msg_len_words; - - /* CRC (currently 0) goes at end of msg */ - word_ptr = (u32 *)(ta_ctx->msgptr + msg_offset); - *word_ptr = 0; -} - -/** - * sep_start_inbound_msg - - * @ta_ctx: pointer to struct this_task_ctx - * @msg_offset: offset to place for the next word in the message - * @returns: 0 for success; error value for failure - * Set up pointer in message pool for inbound message - */ -static u32 sep_start_inbound_msg(struct this_task_ctx *ta_ctx, u32 *msg_offset) -{ - u32 *word_ptr; - u32 token; - u32 error = SEP_OK; - - *msg_offset = sizeof(u32) * 2; - word_ptr = (u32 *)ta_ctx->msgptr; - token = *word_ptr; - ta_ctx->msg_len_words = *(word_ptr + 1); - - if (token != SEP_START_MSG_TOKEN) { - error = SEP_INVALID_START; - goto end_function; - } - -end_function: - - return error; -} - -/** - * sep_write_msg - - * @ta_ctx: pointer to struct this_task_ctx - * @in_addr: pointer to start of parameter - * @size: size of parameter to copy (in bytes) - * @max_size: size to move up offset; SEP mesg is in word sizes - * @msg_offset: pointer to current offset (is updated) - * @byte_array: flag ti indicate whether endian must be changed - * Copies data into the message area from caller - */ -static void sep_write_msg(struct this_task_ctx *ta_ctx, void *in_addr, - u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) -{ - u32 *word_ptr; - void *void_ptr; - - void_ptr = ta_ctx->msgptr + *msg_offset; - word_ptr = (u32 *)void_ptr; - memcpy(void_ptr, in_addr, size); - *msg_offset += max_size; - - /* Do we need to manipulate endian? */ - if (byte_array) { - u32 i; - - for (i = 0; i < ((size + 3) / 4); i += 1) - *(word_ptr + i) = CHG_ENDIAN(*(word_ptr + i)); - } -} - -/** - * sep_make_header - * @ta_ctx: pointer to struct this_task_ctx - * @msg_offset: pointer to current offset (is updated) - * @op_code: op code to put into message - * Puts op code into message and updates offset - */ -static void sep_make_header(struct this_task_ctx *ta_ctx, u32 *msg_offset, - u32 op_code) -{ - u32 *word_ptr; - - *msg_offset = sep_start_msg(ta_ctx); - word_ptr = (u32 *)(ta_ctx->msgptr + *msg_offset); - *word_ptr = op_code; - *msg_offset += sizeof(u32); -} - - - -/** - * sep_read_msg - - * @ta_ctx: pointer to struct this_task_ctx - * @in_addr: pointer to start of parameter - * @size: size of parameter to copy (in bytes) - * @max_size: size to move up offset; SEP mesg is in word sizes - * @msg_offset: pointer to current offset (is updated) - * @byte_array: flag ti indicate whether endian must be changed - * Copies data out of the message area to caller - */ -static void sep_read_msg(struct this_task_ctx *ta_ctx, void *in_addr, - u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) -{ - u32 *word_ptr; - void *void_ptr; - - void_ptr = ta_ctx->msgptr + *msg_offset; - word_ptr = (u32 *)void_ptr; - - /* Do we need to manipulate endian? */ - if (byte_array) { - u32 i; - - for (i = 0; i < ((size + 3) / 4); i += 1) - *(word_ptr + i) = CHG_ENDIAN(*(word_ptr + i)); - } - - memcpy(in_addr, void_ptr, size); - *msg_offset += max_size; -} - -/** - * sep_verify_op - - * @ta_ctx: pointer to struct this_task_ctx - * @op_code: expected op_code - * @msg_offset: pointer to current offset (is updated) - * @returns: 0 for success; error for failure - */ -static u32 sep_verify_op(struct this_task_ctx *ta_ctx, u32 op_code, - u32 *msg_offset) -{ - u32 error; - u32 in_ary[2]; - - struct sep_device *sep = ta_ctx->sep_used; - - dev_dbg(&sep->pdev->dev, "dumping return message\n"); - error = sep_start_inbound_msg(ta_ctx, msg_offset); - if (error) { - dev_warn(&sep->pdev->dev, - "sep_start_inbound_msg error\n"); - return error; - } - - sep_read_msg(ta_ctx, in_ary, sizeof(u32) * 2, sizeof(u32) * 2, - msg_offset, 0); - - if (in_ary[0] != op_code) { - dev_warn(&sep->pdev->dev, - "sep got back wrong opcode\n"); - dev_warn(&sep->pdev->dev, - "got back %x; expected %x\n", - in_ary[0], op_code); - return SEP_WRONG_OPCODE; - } - - if (in_ary[1] != SEP_OK) { - dev_warn(&sep->pdev->dev, - "sep execution error\n"); - dev_warn(&sep->pdev->dev, - "got back %x; expected %x\n", - in_ary[1], SEP_OK); - return in_ary[0]; - } - -return 0; -} - -/** - * sep_read_context - - * @ta_ctx: pointer to struct this_task_ctx - * @msg_offset: point to current place in SEP msg; is updated - * @dst: pointer to place to put the context - * @len: size of the context structure (differs for crypro/hash) - * This function reads the context from the msg area - * There is a special way the vendor needs to have the maximum - * length calculated so that the msg_offset is updated properly; - * it skips over some words in the msg area depending on the size - * of the context - */ -static void sep_read_context(struct this_task_ctx *ta_ctx, u32 *msg_offset, - void *dst, u32 len) -{ - u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); - - sep_read_msg(ta_ctx, dst, len, max_length, msg_offset, 0); -} - -/** - * sep_write_context - - * @ta_ctx: pointer to struct this_task_ctx - * @msg_offset: point to current place in SEP msg; is updated - * @src: pointer to the current context - * @len: size of the context structure (differs for crypro/hash) - * This function writes the context to the msg area - * There is a special way the vendor needs to have the maximum - * length calculated so that the msg_offset is updated properly; - * it skips over some words in the msg area depending on the size - * of the context - */ -static void sep_write_context(struct this_task_ctx *ta_ctx, u32 *msg_offset, - void *src, u32 len) -{ - u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); - - sep_write_msg(ta_ctx, src, len, max_length, msg_offset, 0); -} - -/** - * sep_clear_out - - * @ta_ctx: pointer to struct this_task_ctx - * Clear out crypto related values in sep device structure - * to enable device to be used by anyone; either kernel - * crypto or userspace app via middleware - */ -static void sep_clear_out(struct this_task_ctx *ta_ctx) -{ - if (ta_ctx->src_sg_hold) { - sep_free_sg_buf(ta_ctx->src_sg_hold); - ta_ctx->src_sg_hold = NULL; - } - - if (ta_ctx->dst_sg_hold) { - sep_free_sg_buf(ta_ctx->dst_sg_hold); - ta_ctx->dst_sg_hold = NULL; - } - - ta_ctx->src_sg = NULL; - ta_ctx->dst_sg = NULL; - - sep_free_dma_table_data_handler(ta_ctx->sep_used, &ta_ctx->dma_ctx); - - if (ta_ctx->i_own_sep) { - /** - * The following unlocks the sep and makes it available - * to any other application - * First, null out crypto entries in sep before releasing it - */ - ta_ctx->sep_used->current_hash_req = NULL; - ta_ctx->sep_used->current_cypher_req = NULL; - ta_ctx->sep_used->current_request = 0; - ta_ctx->sep_used->current_hash_stage = 0; - ta_ctx->sep_used->ta_ctx = NULL; - ta_ctx->sep_used->in_kernel = 0; - - ta_ctx->call_status.status = 0; - - /* Remove anything confidential */ - memset(ta_ctx->sep_used->shared_addr, 0, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - sep_queue_status_remove(ta_ctx->sep_used, &ta_ctx->queue_elem); - -#ifdef SEP_ENABLE_RUNTIME_PM - ta_ctx->sep_used->in_use = 0; - pm_runtime_mark_last_busy(&ta_ctx->sep_used->pdev->dev); - pm_runtime_put_autosuspend(&ta_ctx->sep_used->pdev->dev); -#endif - - clear_bit(SEP_WORKING_LOCK_BIT, - &ta_ctx->sep_used->in_use_flags); - ta_ctx->sep_used->pid_doing_transaction = 0; - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "[PID%d] waking up next transaction\n", - current->pid); - - clear_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, - &ta_ctx->sep_used->in_use_flags); - wake_up(&ta_ctx->sep_used->event_transactions); - - ta_ctx->i_own_sep = 0; - } -} - -/** - * Release crypto infrastructure from EINPROGRESS and - * clear sep_dev so that SEP is available to anyone - */ -static void sep_crypto_release(struct sep_system_ctx *sctx, - struct this_task_ctx *ta_ctx, u32 error) -{ - struct ahash_request *hash_req = ta_ctx->current_hash_req; - struct ablkcipher_request *cypher_req = - ta_ctx->current_cypher_req; - struct sep_device *sep = ta_ctx->sep_used; - - sep_clear_out(ta_ctx); - - /** - * This may not yet exist depending when we - * chose to bail out. If it does exist, set - * it to 1 - */ - if (ta_ctx->are_we_done_yet != NULL) - *ta_ctx->are_we_done_yet = 1; - - if (cypher_req != NULL) { - if ((sctx->key_sent == 1) || - ((error != 0) && (error != -EINPROGRESS))) { - if (cypher_req->base.complete == NULL) { - dev_dbg(&sep->pdev->dev, - "release is null for cypher!"); - } else { - cypher_req->base.complete( - &cypher_req->base, error); - } - } - } - - if (hash_req != NULL) { - if (hash_req->base.complete == NULL) { - dev_dbg(&sep->pdev->dev, - "release is null for hash!"); - } else { - hash_req->base.complete( - &hash_req->base, error); - } - } -} - -/** - * This is where we grab the sep itself and tell it to do something. - * It will sleep if the sep is currently busy - * and it will return 0 if sep is now ours; error value if there - * were problems - */ -static int sep_crypto_take_sep(struct this_task_ctx *ta_ctx) -{ - struct sep_device *sep = ta_ctx->sep_used; - int result; - struct sep_msgarea_hdr *my_msg_header; - - my_msg_header = (struct sep_msgarea_hdr *)ta_ctx->msg; - - /* add to status queue */ - ta_ctx->queue_elem = sep_queue_status_add(sep, my_msg_header->opcode, - ta_ctx->nbytes, current->pid, - current->comm, sizeof(current->comm)); - - if (!ta_ctx->queue_elem) { - dev_dbg(&sep->pdev->dev, - "[PID%d] updating queue status error\n", current->pid); - return -EINVAL; - } - - /* get the device; this can sleep */ - result = sep_wait_transaction(sep); - if (result) - return result; - - if (sep_dev->power_save_setup == 1) - pm_runtime_get_sync(&sep_dev->pdev->dev); - - /* Copy in the message */ - memcpy(sep->shared_addr, ta_ctx->msg, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - /* Copy in the dcb information if there is any */ - if (ta_ctx->dcb_region) { - result = sep_activate_dcb_dmatables_context(sep, - &ta_ctx->dcb_region, &ta_ctx->dmatables_region, - ta_ctx->dma_ctx); - if (result) - return result; - } - - /* Mark the device so we know how to finish the job in the tasklet */ - if (ta_ctx->current_hash_req) - sep->current_hash_req = ta_ctx->current_hash_req; - else - sep->current_cypher_req = ta_ctx->current_cypher_req; - - sep->current_request = ta_ctx->current_request; - sep->current_hash_stage = ta_ctx->current_hash_stage; - sep->ta_ctx = ta_ctx; - sep->in_kernel = 1; - ta_ctx->i_own_sep = 1; - - /* need to set bit first to avoid race condition with interrupt */ - set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &ta_ctx->call_status.status); - - result = sep_send_command_handler(sep); - - dev_dbg(&sep->pdev->dev, "[PID%d]: sending command to the sep\n", - current->pid); - - if (!result) - dev_dbg(&sep->pdev->dev, "[PID%d]: command sent okay\n", - current->pid); - else { - dev_dbg(&sep->pdev->dev, "[PID%d]: cant send command\n", - current->pid); - clear_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &ta_ctx->call_status.status); - } - - return result; -} - -/** - * This function sets things up for a crypto data block process - * This does all preparation, but does not try to grab the - * sep - * @req: pointer to struct ablkcipher_request - * returns: 0 if all went well, non zero if error - */ -static int sep_crypto_block_data(struct ablkcipher_request *req) -{ - - int int_error; - u32 msg_offset; - static u32 msg[10]; - void *src_ptr; - void *dst_ptr; - - static char small_buf[100]; - ssize_t copy_result; - int result; - - struct scatterlist *new_sg; - struct this_task_ctx *ta_ctx; - struct crypto_ablkcipher *tfm; - struct sep_system_ctx *sctx; - - struct sep_des_internal_context *des_internal; - struct sep_aes_internal_context *aes_internal; - - ta_ctx = ablkcipher_request_ctx(req); - tfm = crypto_ablkcipher_reqtfm(req); - sctx = crypto_ablkcipher_ctx(tfm); - - /* start the walk on scatterlists */ - ablkcipher_walk_init(&ta_ctx->walk, req->src, req->dst, req->nbytes); - dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep crypto block data size of %x\n", - req->nbytes); - - int_error = ablkcipher_walk_phys(req, &ta_ctx->walk); - if (int_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", - int_error); - return -ENOMEM; - } - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "crypto block: src is %lx dst is %lx\n", - (unsigned long)req->src, (unsigned long)req->dst); - - /* Make sure all pages are even block */ - int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, - req->nbytes, ta_ctx->walk.blocksize, &new_sg, 1); - - if (int_error < 0) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball page error\n"); - return int_error; - } else if (int_error == 1) { - ta_ctx->src_sg = new_sg; - ta_ctx->src_sg_hold = new_sg; - } else { - ta_ctx->src_sg = req->src; - ta_ctx->src_sg_hold = NULL; - } - - int_error = sep_oddball_pages(ta_ctx->sep_used, req->dst, - req->nbytes, ta_ctx->walk.blocksize, &new_sg, 0); - - if (int_error < 0) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", - int_error); - return int_error; - } else if (int_error == 1) { - ta_ctx->dst_sg = new_sg; - ta_ctx->dst_sg_hold = new_sg; - } else { - ta_ctx->dst_sg = req->dst; - ta_ctx->dst_sg_hold = NULL; - } - - /* set nbytes for queue status */ - ta_ctx->nbytes = req->nbytes; - - /* Key already done; this is for data */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending data\n"); - - /* check for valid data and proper spacing */ - src_ptr = sg_virt(ta_ctx->src_sg); - dst_ptr = sg_virt(ta_ctx->dst_sg); - - if (!src_ptr || !dst_ptr || - (ta_ctx->current_cypher_req->nbytes % - crypto_ablkcipher_blocksize(tfm))) { - - dev_warn(&ta_ctx->sep_used->pdev->dev, - "cipher block size odd\n"); - dev_warn(&ta_ctx->sep_used->pdev->dev, - "cipher block size is %x\n", - crypto_ablkcipher_blocksize(tfm)); - dev_warn(&ta_ctx->sep_used->pdev->dev, - "cipher data size is %x\n", - ta_ctx->current_cypher_req->nbytes); - return -EINVAL; - } - - if (partial_overlap(src_ptr, dst_ptr, - ta_ctx->current_cypher_req->nbytes)) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "block partial overlap\n"); - return -EINVAL; - } - - /* Put together the message */ - sep_make_header(ta_ctx, &msg_offset, ta_ctx->block_opcode); - - /* If des, and size is 1 block, put directly in msg */ - if ((ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) && - (req->nbytes == crypto_ablkcipher_blocksize(tfm))) { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "writing out one block des\n"); - - copy_result = sg_copy_to_buffer( - ta_ctx->src_sg, sep_sg_nents(ta_ctx->src_sg), - small_buf, crypto_ablkcipher_blocksize(tfm)); - - if (copy_result != crypto_ablkcipher_blocksize(tfm)) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "des block copy failed\n"); - return -ENOMEM; - } - - /* Put data into message */ - sep_write_msg(ta_ctx, small_buf, - crypto_ablkcipher_blocksize(tfm), - crypto_ablkcipher_blocksize(tfm) * 2, - &msg_offset, 1); - - /* Put size into message */ - sep_write_msg(ta_ctx, &req->nbytes, - sizeof(u32), sizeof(u32), &msg_offset, 0); - } else { - /* Otherwise, fill out dma tables */ - ta_ctx->dcb_input_data.app_in_address = src_ptr; - ta_ctx->dcb_input_data.data_in_size = req->nbytes; - ta_ctx->dcb_input_data.app_out_address = dst_ptr; - ta_ctx->dcb_input_data.block_size = - crypto_ablkcipher_blocksize(tfm); - ta_ctx->dcb_input_data.tail_block_size = 0; - ta_ctx->dcb_input_data.is_applet = 0; - ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; - ta_ctx->dcb_input_data.dst_sg = ta_ctx->dst_sg; - - result = sep_create_dcb_dmatables_context_kernel( - ta_ctx->sep_used, - &ta_ctx->dcb_region, - &ta_ctx->dmatables_region, - &ta_ctx->dma_ctx, - &ta_ctx->dcb_input_data, - 1); - if (result) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "crypto dma table create failed\n"); - return -EINVAL; - } - - /* Portion of msg is nulled (no data) */ - msg[0] = (u32)0; - msg[1] = (u32)0; - msg[2] = (u32)0; - msg[3] = (u32)0; - msg[4] = (u32)0; - sep_write_msg(ta_ctx, (void *)msg, sizeof(u32) * 5, - sizeof(u32) * 5, &msg_offset, 0); - } - - /** - * Before we write the message, we need to overwrite the - * vendor's IV with the one from our own ablkcipher walk - * iv because this is needed for dm-crypt - */ - sep_dump_ivs(req, "sending data block to sep\n"); - if ((ta_ctx->current_request == DES_CBC) && - (ta_ctx->des_opmode == SEP_DES_CBC)) { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "overwrite vendor iv on DES\n"); - des_internal = (struct sep_des_internal_context *) - sctx->des_private_ctx.ctx_buf; - memcpy((void *)des_internal->iv_context, - ta_ctx->walk.iv, crypto_ablkcipher_ivsize(tfm)); - } else if ((ta_ctx->current_request == AES_CBC) && - (ta_ctx->aes_opmode == SEP_AES_CBC)) { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "overwrite vendor iv on AES\n"); - aes_internal = (struct sep_aes_internal_context *) - sctx->aes_private_ctx.cbuff; - memcpy((void *)aes_internal->aes_ctx_iv, - ta_ctx->walk.iv, crypto_ablkcipher_ivsize(tfm)); - } - - /* Write context into message */ - if (ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) { - sep_write_context(ta_ctx, &msg_offset, - &sctx->des_private_ctx, - sizeof(struct sep_des_private_context)); - } else { - sep_write_context(ta_ctx, &msg_offset, - &sctx->aes_private_ctx, - sizeof(struct sep_aes_private_context)); - } - - /* conclude message */ - sep_end_msg(ta_ctx, msg_offset); - - /* Parent (caller) is now ready to tell the sep to do ahead */ - return 0; -} - - -/** - * This function sets things up for a crypto key submit process - * This does all preparation, but does not try to grab the - * sep - * @req: pointer to struct ablkcipher_request - * returns: 0 if all went well, non zero if error - */ -static int sep_crypto_send_key(struct ablkcipher_request *req) -{ - - int int_error; - u32 msg_offset; - static u32 msg[10]; - - u32 max_length; - struct this_task_ctx *ta_ctx; - struct crypto_ablkcipher *tfm; - struct sep_system_ctx *sctx; - - ta_ctx = ablkcipher_request_ctx(req); - tfm = crypto_ablkcipher_reqtfm(req); - sctx = crypto_ablkcipher_ctx(tfm); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending key\n"); - - /* start the walk on scatterlists */ - ablkcipher_walk_init(&ta_ctx->walk, req->src, req->dst, req->nbytes); - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep crypto block data size of %x\n", req->nbytes); - - int_error = ablkcipher_walk_phys(req, &ta_ctx->walk); - if (int_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", - int_error); - return -ENOMEM; - } - - /* check iv */ - if ((ta_ctx->current_request == DES_CBC) && - (ta_ctx->des_opmode == SEP_DES_CBC)) { - if (!ta_ctx->walk.iv) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "no iv found\n"); - return -EINVAL; - } - - memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); - } - - if ((ta_ctx->current_request == AES_CBC) && - (ta_ctx->aes_opmode == SEP_AES_CBC)) { - if (!ta_ctx->walk.iv) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "no iv found\n"); - return -EINVAL; - } - - memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); - } - - /* put together message to SEP */ - /* Start with op code */ - sep_make_header(ta_ctx, &msg_offset, ta_ctx->init_opcode); - - /* now deal with IV */ - if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { - if (ta_ctx->des_opmode == SEP_DES_CBC) { - sep_write_msg(ta_ctx, ta_ctx->iv, - SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, - &msg_offset, 1); - } else { - /* Skip if ECB */ - msg_offset += 4 * sizeof(u32); - } - } else { - max_length = ((SEP_AES_IV_SIZE_BYTES + 3) / - sizeof(u32)) * sizeof(u32); - if (ta_ctx->aes_opmode == SEP_AES_CBC) { - sep_write_msg(ta_ctx, ta_ctx->iv, - SEP_AES_IV_SIZE_BYTES, max_length, - &msg_offset, 1); - } else { - /* Skip if ECB */ - msg_offset += max_length; - } - } - - /* load the key */ - if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { - sep_write_msg(ta_ctx, (void *)&sctx->key.des.key1, - sizeof(u32) * 8, sizeof(u32) * 8, - &msg_offset, 1); - - msg[0] = (u32)sctx->des_nbr_keys; - msg[1] = (u32)ta_ctx->des_encmode; - msg[2] = (u32)ta_ctx->des_opmode; - - sep_write_msg(ta_ctx, (void *)msg, - sizeof(u32) * 3, sizeof(u32) * 3, - &msg_offset, 0); - } else { - sep_write_msg(ta_ctx, (void *)&sctx->key.aes, - sctx->keylen, - SEP_AES_MAX_KEY_SIZE_BYTES, - &msg_offset, 1); - - msg[0] = (u32)sctx->aes_key_size; - msg[1] = (u32)ta_ctx->aes_encmode; - msg[2] = (u32)ta_ctx->aes_opmode; - msg[3] = (u32)0; /* Secret key is not used */ - sep_write_msg(ta_ctx, (void *)msg, - sizeof(u32) * 4, sizeof(u32) * 4, - &msg_offset, 0); - } - - /* conclude message */ - sep_end_msg(ta_ctx, msg_offset); - - /* Parent (caller) is now ready to tell the sep to do ahead */ - return 0; -} - - -/* This needs to be run as a work queue as it can be put asleep */ -static void sep_crypto_block(void *data) -{ - unsigned long end_time; - - int result; - - struct ablkcipher_request *req; - struct this_task_ctx *ta_ctx; - struct crypto_ablkcipher *tfm; - struct sep_system_ctx *sctx; - int are_we_done_yet; - - req = (struct ablkcipher_request *)data; - ta_ctx = ablkcipher_request_ctx(req); - tfm = crypto_ablkcipher_reqtfm(req); - sctx = crypto_ablkcipher_ctx(tfm); - - ta_ctx->are_we_done_yet = &are_we_done_yet; - - pr_debug("sep_crypto_block\n"); - pr_debug("tfm is %p sctx is %p ta_ctx is %p\n", - tfm, sctx, ta_ctx); - pr_debug("key_sent is %d\n", sctx->key_sent); - - /* do we need to send the key */ - if (sctx->key_sent == 0) { - are_we_done_yet = 0; - result = sep_crypto_send_key(req); /* prep to send key */ - if (result != 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "could not prep key %x\n", result); - sep_crypto_release(sctx, ta_ctx, result); - return; - } - - result = sep_crypto_take_sep(ta_ctx); - if (result) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep_crypto_take_sep for key send failed\n"); - sep_crypto_release(sctx, ta_ctx, result); - return; - } - - /* now we sit and wait up to a fixed time for completion */ - end_time = jiffies + (WAIT_TIME * HZ); - while ((time_before(jiffies, end_time)) && - (are_we_done_yet == 0)) - schedule(); - - /* Done waiting; still not done yet? */ - if (are_we_done_yet == 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "Send key job never got done\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - - /* Set the key sent variable so this can be skipped later */ - sctx->key_sent = 1; - } - - /* Key sent (or maybe not if we did not have to), now send block */ - are_we_done_yet = 0; - - result = sep_crypto_block_data(req); - - if (result != 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "could prep not send block %x\n", result); - sep_crypto_release(sctx, ta_ctx, result); - return; - } - - result = sep_crypto_take_sep(ta_ctx); - if (result) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep_crypto_take_sep for block send failed\n"); - sep_crypto_release(sctx, ta_ctx, result); - return; - } - - /* now we sit and wait up to a fixed time for completion */ - end_time = jiffies + (WAIT_TIME * HZ); - while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) - schedule(); - - /* Done waiting; still not done yet? */ - if (are_we_done_yet == 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "Send block job never got done\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - - /* That's it; entire thing done, get out of queue */ - - pr_debug("crypto_block leaving\n"); - pr_debug("tfm is %p sctx is %p ta_ctx is %p\n", tfm, sctx, ta_ctx); -} - -/** - * Post operation (after interrupt) for crypto block - */ -static u32 crypto_post_op(struct sep_device *sep) -{ - /* HERE */ - u32 u32_error; - u32 msg_offset; - - ssize_t copy_result; - static char small_buf[100]; - - struct ablkcipher_request *req; - struct this_task_ctx *ta_ctx; - struct sep_system_ctx *sctx; - struct crypto_ablkcipher *tfm; - - struct sep_des_internal_context *des_internal; - struct sep_aes_internal_context *aes_internal; - - if (!sep->current_cypher_req) - return -EINVAL; - - /* hold req since we need to submit work after clearing sep */ - req = sep->current_cypher_req; - - ta_ctx = ablkcipher_request_ctx(sep->current_cypher_req); - tfm = crypto_ablkcipher_reqtfm(sep->current_cypher_req); - sctx = crypto_ablkcipher_ctx(tfm); - - pr_debug("crypto_post op\n"); - pr_debug("key_sent is %d tfm is %p sctx is %p ta_ctx is %p\n", - sctx->key_sent, tfm, sctx, ta_ctx); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op\n"); - dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op message dump\n"); - - /* first bring msg from shared area to local area */ - memcpy(ta_ctx->msg, sep->shared_addr, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - /* Is this the result of performing init (key to SEP */ - if (sctx->key_sent == 0) { - - /* Did SEP do it okay */ - u32_error = sep_verify_op(ta_ctx, ta_ctx->init_opcode, - &msg_offset); - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "aes init error %x\n", u32_error); - sep_crypto_release(sctx, ta_ctx, u32_error); - return u32_error; - } - - /* Read Context */ - if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { - sep_read_context(ta_ctx, &msg_offset, - &sctx->des_private_ctx, - sizeof(struct sep_des_private_context)); - } else { - sep_read_context(ta_ctx, &msg_offset, - &sctx->aes_private_ctx, - sizeof(struct sep_aes_private_context)); - } - - sep_dump_ivs(req, "after sending key to sep\n"); - - /* key sent went okay; release sep, and set are_we_done_yet */ - sctx->key_sent = 1; - sep_crypto_release(sctx, ta_ctx, -EINPROGRESS); - - } else { - - /** - * This is the result of a block request - */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "crypto_post_op block response\n"); - - u32_error = sep_verify_op(ta_ctx, ta_ctx->block_opcode, - &msg_offset); - - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep block error %x\n", u32_error); - sep_crypto_release(sctx, ta_ctx, u32_error); - return -EINVAL; - } - - if (ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "post op for DES\n"); - - /* special case for 1 block des */ - if (sep->current_cypher_req->nbytes == - crypto_ablkcipher_blocksize(tfm)) { - - sep_read_msg(ta_ctx, small_buf, - crypto_ablkcipher_blocksize(tfm), - crypto_ablkcipher_blocksize(tfm) * 2, - &msg_offset, 1); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "reading in block des\n"); - - copy_result = sg_copy_from_buffer( - ta_ctx->dst_sg, - sep_sg_nents(ta_ctx->dst_sg), - small_buf, - crypto_ablkcipher_blocksize(tfm)); - - if (copy_result != - crypto_ablkcipher_blocksize(tfm)) { - - dev_warn(&ta_ctx->sep_used->pdev->dev, - "des block copy failed\n"); - sep_crypto_release(sctx, ta_ctx, - -ENOMEM); - return -ENOMEM; - } - } - - /* Read Context */ - sep_read_context(ta_ctx, &msg_offset, - &sctx->des_private_ctx, - sizeof(struct sep_des_private_context)); - } else { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "post op for AES\n"); - - /* Skip the MAC Output */ - msg_offset += (sizeof(u32) * 4); - - /* Read Context */ - sep_read_context(ta_ctx, &msg_offset, - &sctx->aes_private_ctx, - sizeof(struct sep_aes_private_context)); - } - - /* Copy to correct sg if this block had oddball pages */ - if (ta_ctx->dst_sg_hold) - sep_copy_sg(ta_ctx->sep_used, - ta_ctx->dst_sg, - ta_ctx->current_cypher_req->dst, - ta_ctx->current_cypher_req->nbytes); - - /** - * Copy the iv's back to the walk.iv - * This is required for dm_crypt - */ - sep_dump_ivs(req, "got data block from sep\n"); - if ((ta_ctx->current_request == DES_CBC) && - (ta_ctx->des_opmode == SEP_DES_CBC)) { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "returning result iv to walk on DES\n"); - des_internal = (struct sep_des_internal_context *) - sctx->des_private_ctx.ctx_buf; - memcpy(ta_ctx->walk.iv, - (void *)des_internal->iv_context, - crypto_ablkcipher_ivsize(tfm)); - } else if ((ta_ctx->current_request == AES_CBC) && - (ta_ctx->aes_opmode == SEP_AES_CBC)) { - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "returning result iv to walk on AES\n"); - aes_internal = (struct sep_aes_internal_context *) - sctx->aes_private_ctx.cbuff; - memcpy(ta_ctx->walk.iv, - (void *)aes_internal->aes_ctx_iv, - crypto_ablkcipher_ivsize(tfm)); - } - - /* finished, release everything */ - sep_crypto_release(sctx, ta_ctx, 0); - } - pr_debug("crypto_post_op done\n"); - pr_debug("key_sent is %d tfm is %p sctx is %p ta_ctx is %p\n", - sctx->key_sent, tfm, sctx, ta_ctx); - - return 0; -} - -static u32 hash_init_post_op(struct sep_device *sep) -{ - u32 u32_error; - u32 msg_offset; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash init post op\n"); - - /* first bring msg from shared area to local area */ - memcpy(ta_ctx->msg, sep->shared_addr, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - u32_error = sep_verify_op(ta_ctx, SEP_HASH_INIT_OPCODE, - &msg_offset); - - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "hash init error %x\n", - u32_error); - sep_crypto_release(sctx, ta_ctx, u32_error); - return u32_error; - } - - /* Read Context */ - sep_read_context(ta_ctx, &msg_offset, - &sctx->hash_private_ctx, - sizeof(struct sep_hash_private_context)); - - /* Signal to crypto infrastructure and clear out */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash init post op done\n"); - sep_crypto_release(sctx, ta_ctx, 0); - return 0; -} - -static u32 hash_update_post_op(struct sep_device *sep) -{ - u32 u32_error; - u32 msg_offset; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash update post op\n"); - - /* first bring msg from shared area to local area */ - memcpy(ta_ctx->msg, sep->shared_addr, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - u32_error = sep_verify_op(ta_ctx, SEP_HASH_UPDATE_OPCODE, - &msg_offset); - - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "hash init error %x\n", - u32_error); - sep_crypto_release(sctx, ta_ctx, u32_error); - return u32_error; - } - - /* Read Context */ - sep_read_context(ta_ctx, &msg_offset, - &sctx->hash_private_ctx, - sizeof(struct sep_hash_private_context)); - - /** - * Following is only for finup; if we just completed the - * data portion of finup, we now need to kick off the - * finish portion of finup. - */ - - if (ta_ctx->sep_used->current_hash_stage == HASH_FINUP_DATA) { - - /* first reset stage to HASH_FINUP_FINISH */ - ta_ctx->sep_used->current_hash_stage = HASH_FINUP_FINISH; - - /* now enqueue the finish operation */ - spin_lock_irq(&queue_lock); - u32_error = crypto_enqueue_request(&sep_queue, - &ta_ctx->sep_used->current_hash_req->base); - spin_unlock_irq(&queue_lock); - - if ((u32_error != 0) && (u32_error != -EINPROGRESS)) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "spe cypher post op cant queue\n"); - sep_crypto_release(sctx, ta_ctx, u32_error); - return u32_error; - } - - /* schedule the data send */ - u32_error = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "cant submit work sep_crypto_block\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return -EINVAL; - } - } - - /* Signal to crypto infrastructure and clear out */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash update post op done\n"); - sep_crypto_release(sctx, ta_ctx, 0); - return 0; -} - -static u32 hash_final_post_op(struct sep_device *sep) -{ - int max_length; - u32 u32_error; - u32 msg_offset; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash final post op\n"); - - /* first bring msg from shared area to local area */ - memcpy(ta_ctx->msg, sep->shared_addr, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - u32_error = sep_verify_op(ta_ctx, SEP_HASH_FINISH_OPCODE, - &msg_offset); - - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, "hash finish error %x\n", - u32_error); - sep_crypto_release(sctx, ta_ctx, u32_error); - return u32_error; - } - - /* Grab the result */ - if (ta_ctx->current_hash_req->result == NULL) { - /* Oops, null buffer; error out here */ - dev_warn(&ta_ctx->sep_used->pdev->dev, - "hash finish null buffer\n"); - sep_crypto_release(sctx, ta_ctx, (u32)-ENOMEM); - return -ENOMEM; - } - - max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / - sizeof(u32)) * sizeof(u32); - - sep_read_msg(ta_ctx, - ta_ctx->current_hash_req->result, - crypto_ahash_digestsize(tfm), max_length, - &msg_offset, 0); - - /* Signal to crypto infrastructure and clear out */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash finish post op done\n"); - sep_crypto_release(sctx, ta_ctx, 0); - return 0; -} - -static u32 hash_digest_post_op(struct sep_device *sep) -{ - int max_length; - u32 u32_error; - u32 msg_offset; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash digest post op\n"); - - /* first bring msg from shared area to local area */ - memcpy(ta_ctx->msg, sep->shared_addr, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - u32_error = sep_verify_op(ta_ctx, SEP_HASH_SINGLE_OPCODE, - &msg_offset); - - if (u32_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "hash digest finish error %x\n", u32_error); - - sep_crypto_release(sctx, ta_ctx, u32_error); - return u32_error; - } - - /* Grab the result */ - if (ta_ctx->current_hash_req->result == NULL) { - /* Oops, null buffer; error out here */ - dev_warn(&ta_ctx->sep_used->pdev->dev, - "hash digest finish null buffer\n"); - sep_crypto_release(sctx, ta_ctx, (u32)-ENOMEM); - return -ENOMEM; - } - - max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / - sizeof(u32)) * sizeof(u32); - - sep_read_msg(ta_ctx, - ta_ctx->current_hash_req->result, - crypto_ahash_digestsize(tfm), max_length, - &msg_offset, 0); - - /* Signal to crypto infrastructure and clear out */ - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash digest finish post op done\n"); - - sep_crypto_release(sctx, ta_ctx, 0); - return 0; -} - -/** - * The sep_finish function is the function that is scheduled (via tasklet) - * by the interrupt service routine when the SEP sends and interrupt - * This is only called by the interrupt handler as a tasklet. - */ -static void sep_finish(unsigned long data) -{ - struct sep_device *sep_dev; - int res; - - res = 0; - - if (data == 0) { - pr_debug("sep_finish called with null data\n"); - return; - } - - sep_dev = (struct sep_device *)data; - if (sep_dev == NULL) { - pr_debug("sep_finish; sep_dev is NULL\n"); - return; - } - - if (sep_dev->in_kernel == (u32)0) { - dev_warn(&sep_dev->pdev->dev, - "sep_finish; not in kernel operation\n"); - return; - } - - /* Did we really do a sep command prior to this? */ - if (0 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &sep_dev->ta_ctx->call_status.status)) { - - dev_warn(&sep_dev->pdev->dev, "[PID%d] sendmsg not called\n", - current->pid); - return; - } - - if (sep_dev->send_ct != sep_dev->reply_ct) { - dev_warn(&sep_dev->pdev->dev, - "[PID%d] poll; no message came back\n", - current->pid); - return; - } - - /* Check for error (In case time ran out) */ - if ((res != 0x0) && (res != 0x8)) { - dev_warn(&sep_dev->pdev->dev, - "[PID%d] poll; poll error GPR3 is %x\n", - current->pid, res); - return; - } - - /* What kind of interrupt from sep was this? */ - res = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - - dev_dbg(&sep_dev->pdev->dev, "[PID%d] GPR2 at crypto finish is %x\n", - current->pid, res); - - /* Print request? */ - if ((res >> 30) & 0x1) { - dev_dbg(&sep_dev->pdev->dev, "[PID%d] sep print req\n", - current->pid); - dev_dbg(&sep_dev->pdev->dev, "[PID%d] contents: %s\n", - current->pid, - (char *)(sep_dev->shared_addr + - SEP_DRIVER_PRINTF_OFFSET_IN_BYTES)); - return; - } - - /* Request for daemon (not currently in POR)? */ - if (res >> 31) { - dev_dbg(&sep_dev->pdev->dev, - "[PID%d] sep request; ignoring\n", - current->pid); - return; - } - - /* If we got here, then we have a replay to a sep command */ - - dev_dbg(&sep_dev->pdev->dev, - "[PID%d] sep reply to command; processing request: %x\n", - current->pid, sep_dev->current_request); - - switch (sep_dev->current_request) { - case AES_CBC: - case AES_ECB: - case DES_CBC: - case DES_ECB: - res = crypto_post_op(sep_dev); - break; - case SHA1: - case MD5: - case SHA224: - case SHA256: - switch (sep_dev->current_hash_stage) { - case HASH_INIT: - res = hash_init_post_op(sep_dev); - break; - case HASH_UPDATE: - case HASH_FINUP_DATA: - res = hash_update_post_op(sep_dev); - break; - case HASH_FINUP_FINISH: - case HASH_FINISH: - res = hash_final_post_op(sep_dev); - break; - case HASH_DIGEST: - res = hash_digest_post_op(sep_dev); - break; - default: - pr_debug("sep - invalid stage for hash finish\n"); - } - break; - default: - pr_debug("sep - invalid request for finish\n"); - } - - if (res) - pr_debug("sep - finish returned error %x\n", res); -} - -static int sep_hash_cra_init(struct crypto_tfm *tfm) - { - const char *alg_name = crypto_tfm_alg_name(tfm); - - pr_debug("sep_hash_cra_init name is %s\n", alg_name); - - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct this_task_ctx)); - return 0; - } - -static void sep_hash_cra_exit(struct crypto_tfm *tfm) -{ - pr_debug("sep_hash_cra_exit\n"); -} - -static void sep_hash_init(void *data) -{ - u32 msg_offset; - int result; - struct ahash_request *req; - struct crypto_ahash *tfm; - struct this_task_ctx *ta_ctx; - struct sep_system_ctx *sctx; - unsigned long end_time; - int are_we_done_yet; - - req = (struct ahash_request *)data; - tfm = crypto_ahash_reqtfm(req); - sctx = crypto_ahash_ctx(tfm); - ta_ctx = ahash_request_ctx(req); - ta_ctx->sep_used = sep_dev; - - ta_ctx->are_we_done_yet = &are_we_done_yet; - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep_hash_init\n"); - ta_ctx->current_hash_stage = HASH_INIT; - /* opcode and mode */ - sep_make_header(ta_ctx, &msg_offset, SEP_HASH_INIT_OPCODE); - sep_write_msg(ta_ctx, &ta_ctx->hash_opmode, - sizeof(u32), sizeof(u32), &msg_offset, 0); - sep_end_msg(ta_ctx, msg_offset); - - are_we_done_yet = 0; - result = sep_crypto_take_sep(ta_ctx); - if (result) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep_hash_init take sep failed\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - } - - /* now we sit and wait up to a fixed time for completion */ - end_time = jiffies + (WAIT_TIME * HZ); - while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) - schedule(); - - /* Done waiting; still not done yet? */ - if (are_we_done_yet == 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash init never got done\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - -} - -static void sep_hash_update(void *data) -{ - int int_error; - u32 msg_offset; - u32 len; - struct sep_hash_internal_context *int_ctx; - u32 block_size; - u32 head_len; - u32 tail_len; - int are_we_done_yet; - - static u32 msg[10]; - static char small_buf[100]; - void *src_ptr; - struct scatterlist *new_sg; - ssize_t copy_result; - struct ahash_request *req; - struct crypto_ahash *tfm; - struct this_task_ctx *ta_ctx; - struct sep_system_ctx *sctx; - unsigned long end_time; - - req = (struct ahash_request *)data; - tfm = crypto_ahash_reqtfm(req); - sctx = crypto_ahash_ctx(tfm); - ta_ctx = ahash_request_ctx(req); - ta_ctx->sep_used = sep_dev; - - ta_ctx->are_we_done_yet = &are_we_done_yet; - - /* length for queue status */ - ta_ctx->nbytes = req->nbytes; - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep_hash_update\n"); - ta_ctx->current_hash_stage = HASH_UPDATE; - len = req->nbytes; - - block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); - tail_len = req->nbytes % block_size; - dev_dbg(&ta_ctx->sep_used->pdev->dev, "length is %x\n", len); - dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); - dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); - - /* Compute header/tail sizes */ - int_ctx = (struct sep_hash_internal_context *)&sctx-> - hash_private_ctx.internal_context; - head_len = (block_size - int_ctx->prev_update_bytes) % block_size; - tail_len = (req->nbytes - head_len) % block_size; - - /* Make sure all pages are an even block */ - int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, - req->nbytes, - block_size, &new_sg, 1); - - if (int_error < 0) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "oddball pages error in crash update\n"); - sep_crypto_release(sctx, ta_ctx, -ENOMEM); - return; - } else if (int_error == 1) { - ta_ctx->src_sg = new_sg; - ta_ctx->src_sg_hold = new_sg; - } else { - ta_ctx->src_sg = req->src; - ta_ctx->src_sg_hold = NULL; - } - - src_ptr = sg_virt(ta_ctx->src_sg); - - if ((!req->nbytes) || (!ta_ctx->src_sg)) { - /* null data */ - src_ptr = NULL; - } - - ta_ctx->dcb_input_data.app_in_address = src_ptr; - ta_ctx->dcb_input_data.data_in_size = - req->nbytes - (head_len + tail_len); - ta_ctx->dcb_input_data.app_out_address = NULL; - ta_ctx->dcb_input_data.block_size = block_size; - ta_ctx->dcb_input_data.tail_block_size = 0; - ta_ctx->dcb_input_data.is_applet = 0; - ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; - ta_ctx->dcb_input_data.dst_sg = NULL; - - int_error = sep_create_dcb_dmatables_context_kernel( - ta_ctx->sep_used, - &ta_ctx->dcb_region, - &ta_ctx->dmatables_region, - &ta_ctx->dma_ctx, - &ta_ctx->dcb_input_data, - 1); - if (int_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "hash update dma table create failed\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - - /* Construct message to SEP */ - sep_make_header(ta_ctx, &msg_offset, SEP_HASH_UPDATE_OPCODE); - - msg[0] = (u32)0; - msg[1] = (u32)0; - msg[2] = (u32)0; - - sep_write_msg(ta_ctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, - &msg_offset, 0); - - /* Handle remainders */ - - /* Head */ - sep_write_msg(ta_ctx, &head_len, sizeof(u32), - sizeof(u32), &msg_offset, 0); - - if (head_len) { - copy_result = sg_copy_to_buffer( - req->src, - sep_sg_nents(ta_ctx->src_sg), - small_buf, head_len); - - if (copy_result != head_len) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sg head copy failure in hash block\n"); - sep_crypto_release(sctx, ta_ctx, -ENOMEM); - return; - } - - sep_write_msg(ta_ctx, small_buf, head_len, - sizeof(u32) * 32, &msg_offset, 1); - } else { - msg_offset += sizeof(u32) * 32; - } - - /* Tail */ - sep_write_msg(ta_ctx, &tail_len, sizeof(u32), - sizeof(u32), &msg_offset, 0); - - if (tail_len) { - copy_result = sep_copy_offset_sg( - ta_ctx->sep_used, - ta_ctx->src_sg, - req->nbytes - tail_len, - small_buf, tail_len); - - if (copy_result != tail_len) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sg tail copy failure in hash block\n"); - sep_crypto_release(sctx, ta_ctx, -ENOMEM); - return; - } - - sep_write_msg(ta_ctx, small_buf, tail_len, - sizeof(u32) * 32, &msg_offset, 1); - } else { - msg_offset += sizeof(u32) * 32; - } - - /* Context */ - sep_write_context(ta_ctx, &msg_offset, &sctx->hash_private_ctx, - sizeof(struct sep_hash_private_context)); - - sep_end_msg(ta_ctx, msg_offset); - are_we_done_yet = 0; - int_error = sep_crypto_take_sep(ta_ctx); - if (int_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep_hash_update take sep failed\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - } - - /* now we sit and wait up to a fixed time for completion */ - end_time = jiffies + (WAIT_TIME * HZ); - while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) - schedule(); - - /* Done waiting; still not done yet? */ - if (are_we_done_yet == 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash update never got done\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - -} - -static void sep_hash_final(void *data) -{ - u32 msg_offset; - struct ahash_request *req; - struct crypto_ahash *tfm; - struct this_task_ctx *ta_ctx; - struct sep_system_ctx *sctx; - int result; - unsigned long end_time; - int are_we_done_yet; - - req = (struct ahash_request *)data; - tfm = crypto_ahash_reqtfm(req); - sctx = crypto_ahash_ctx(tfm); - ta_ctx = ahash_request_ctx(req); - ta_ctx->sep_used = sep_dev; - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep_hash_final\n"); - ta_ctx->current_hash_stage = HASH_FINISH; - - ta_ctx->are_we_done_yet = &are_we_done_yet; - - /* opcode and mode */ - sep_make_header(ta_ctx, &msg_offset, SEP_HASH_FINISH_OPCODE); - - /* Context */ - sep_write_context(ta_ctx, &msg_offset, &sctx->hash_private_ctx, - sizeof(struct sep_hash_private_context)); - - sep_end_msg(ta_ctx, msg_offset); - are_we_done_yet = 0; - result = sep_crypto_take_sep(ta_ctx); - if (result) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep_hash_final take sep failed\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - } - - /* now we sit and wait up to a fixed time for completion */ - end_time = jiffies + (WAIT_TIME * HZ); - while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) - schedule(); - - /* Done waiting; still not done yet? */ - if (are_we_done_yet == 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash final job never got done\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - -} - -static void sep_hash_digest(void *data) -{ - int int_error; - u32 msg_offset; - u32 block_size; - u32 msg[10]; - size_t copy_result; - int result; - int are_we_done_yet; - u32 tail_len; - static char small_buf[100]; - struct scatterlist *new_sg; - void *src_ptr; - - struct ahash_request *req; - struct crypto_ahash *tfm; - struct this_task_ctx *ta_ctx; - struct sep_system_ctx *sctx; - unsigned long end_time; - - req = (struct ahash_request *)data; - tfm = crypto_ahash_reqtfm(req); - sctx = crypto_ahash_ctx(tfm); - ta_ctx = ahash_request_ctx(req); - ta_ctx->sep_used = sep_dev; - - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "sep_hash_digest\n"); - ta_ctx->current_hash_stage = HASH_DIGEST; - - ta_ctx->are_we_done_yet = &are_we_done_yet; - - /* length for queue status */ - ta_ctx->nbytes = req->nbytes; - - block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); - tail_len = req->nbytes % block_size; - dev_dbg(&ta_ctx->sep_used->pdev->dev, "length is %x\n", req->nbytes); - dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); - dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); - - /* Make sure all pages are an even block */ - int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, - req->nbytes, - block_size, &new_sg, 1); - - if (int_error < 0) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "oddball pages error in crash update\n"); - sep_crypto_release(sctx, ta_ctx, -ENOMEM); - return; - } else if (int_error == 1) { - ta_ctx->src_sg = new_sg; - ta_ctx->src_sg_hold = new_sg; - } else { - ta_ctx->src_sg = req->src; - ta_ctx->src_sg_hold = NULL; - } - - src_ptr = sg_virt(ta_ctx->src_sg); - - if ((!req->nbytes) || (!ta_ctx->src_sg)) { - /* null data */ - src_ptr = NULL; - } - - ta_ctx->dcb_input_data.app_in_address = src_ptr; - ta_ctx->dcb_input_data.data_in_size = req->nbytes - tail_len; - ta_ctx->dcb_input_data.app_out_address = NULL; - ta_ctx->dcb_input_data.block_size = block_size; - ta_ctx->dcb_input_data.tail_block_size = 0; - ta_ctx->dcb_input_data.is_applet = 0; - ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; - ta_ctx->dcb_input_data.dst_sg = NULL; - - int_error = sep_create_dcb_dmatables_context_kernel( - ta_ctx->sep_used, - &ta_ctx->dcb_region, - &ta_ctx->dmatables_region, - &ta_ctx->dma_ctx, - &ta_ctx->dcb_input_data, - 1); - if (int_error) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "hash update dma table create failed\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - - /* Construct message to SEP */ - sep_make_header(ta_ctx, &msg_offset, SEP_HASH_SINGLE_OPCODE); - sep_write_msg(ta_ctx, &ta_ctx->hash_opmode, - sizeof(u32), sizeof(u32), &msg_offset, 0); - - msg[0] = (u32)0; - msg[1] = (u32)0; - msg[2] = (u32)0; - - sep_write_msg(ta_ctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, - &msg_offset, 0); - - /* Tail */ - sep_write_msg(ta_ctx, &tail_len, sizeof(u32), - sizeof(u32), &msg_offset, 0); - - if (tail_len) { - copy_result = sep_copy_offset_sg( - ta_ctx->sep_used, - ta_ctx->src_sg, - req->nbytes - tail_len, - small_buf, tail_len); - - if (copy_result != tail_len) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sg tail copy failure in hash block\n"); - sep_crypto_release(sctx, ta_ctx, -ENOMEM); - return; - } - - sep_write_msg(ta_ctx, small_buf, tail_len, - sizeof(u32) * 32, &msg_offset, 1); - } else { - msg_offset += sizeof(u32) * 32; - } - - sep_end_msg(ta_ctx, msg_offset); - - are_we_done_yet = 0; - result = sep_crypto_take_sep(ta_ctx); - if (result) { - dev_warn(&ta_ctx->sep_used->pdev->dev, - "sep_hash_digest take sep failed\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - } - - /* now we sit and wait up to a fixed time for completion */ - end_time = jiffies + (WAIT_TIME * HZ); - while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) - schedule(); - - /* Done waiting; still not done yet? */ - if (are_we_done_yet == 0) { - dev_dbg(&ta_ctx->sep_used->pdev->dev, - "hash digest job never got done\n"); - sep_crypto_release(sctx, ta_ctx, -EINVAL); - return; - } - -} - -/** - * This is what is called by each of the API's provided - * in the kernel crypto descriptors. It is run in a process - * context using the kernel workqueues. Therefore it can - * be put to sleep. - */ -static void sep_dequeuer(void *data) -{ - struct crypto_queue *this_queue; - struct crypto_async_request *async_req; - struct crypto_async_request *backlog; - struct ablkcipher_request *cypher_req; - struct ahash_request *hash_req; - struct sep_system_ctx *sctx; - struct crypto_ahash *hash_tfm; - struct this_task_ctx *ta_ctx; - - - this_queue = (struct crypto_queue *)data; - - spin_lock_irq(&queue_lock); - backlog = crypto_get_backlog(this_queue); - async_req = crypto_dequeue_request(this_queue); - spin_unlock_irq(&queue_lock); - - if (!async_req) { - pr_debug("sep crypto queue is empty\n"); - return; - } - - if (backlog) { - pr_debug("sep crypto backlog set\n"); - if (backlog->complete) - backlog->complete(backlog, -EINPROGRESS); - backlog = NULL; - } - - if (!async_req->tfm) { - pr_debug("sep crypto queue null tfm\n"); - return; - } - - if (!async_req->tfm->__crt_alg) { - pr_debug("sep crypto queue null __crt_alg\n"); - return; - } - - if (!async_req->tfm->__crt_alg->cra_type) { - pr_debug("sep crypto queue null cra_type\n"); - return; - } - - /* we have stuff in the queue */ - if (async_req->tfm->__crt_alg->cra_type != - &crypto_ahash_type) { - /* This is for a cypher */ - pr_debug("sep crypto queue doing cipher\n"); - cypher_req = container_of(async_req, - struct ablkcipher_request, - base); - if (!cypher_req) { - pr_debug("sep crypto queue null cypher_req\n"); - return; - } - - sep_crypto_block((void *)cypher_req); - return; - } else { - /* This is a hash */ - pr_debug("sep crypto queue doing hash\n"); - /** - * This is a bit more complex than cipher; we - * need to figure out what type of operation - */ - hash_req = ahash_request_cast(async_req); - if (!hash_req) { - pr_debug("sep crypto queue null hash_req\n"); - return; - } - - hash_tfm = crypto_ahash_reqtfm(hash_req); - if (!hash_tfm) { - pr_debug("sep crypto queue null hash_tfm\n"); - return; - } - - - sctx = crypto_ahash_ctx(hash_tfm); - if (!sctx) { - pr_debug("sep crypto queue null sctx\n"); - return; - } - - ta_ctx = ahash_request_ctx(hash_req); - - if (ta_ctx->current_hash_stage == HASH_INIT) { - pr_debug("sep crypto queue hash init\n"); - sep_hash_init((void *)hash_req); - return; - } else if (ta_ctx->current_hash_stage == HASH_UPDATE) { - pr_debug("sep crypto queue hash update\n"); - sep_hash_update((void *)hash_req); - return; - } else if (ta_ctx->current_hash_stage == HASH_FINISH) { - pr_debug("sep crypto queue hash final\n"); - sep_hash_final((void *)hash_req); - return; - } else if (ta_ctx->current_hash_stage == HASH_DIGEST) { - pr_debug("sep crypto queue hash digest\n"); - sep_hash_digest((void *)hash_req); - return; - } else if (ta_ctx->current_hash_stage == HASH_FINUP_DATA) { - pr_debug("sep crypto queue hash digest\n"); - sep_hash_update((void *)hash_req); - return; - } else if (ta_ctx->current_hash_stage == HASH_FINUP_FINISH) { - pr_debug("sep crypto queue hash digest\n"); - sep_hash_final((void *)hash_req); - return; - } else { - pr_debug("sep crypto queue hash oops nothing\n"); - return; - } - } -} - -static int sep_sha1_init(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha1 init\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA1; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA1; - ta_ctx->current_hash_stage = HASH_INIT; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha1_update(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha1 update\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA1; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA1; - ta_ctx->current_hash_stage = HASH_UPDATE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha1_final(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha1 final\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA1; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA1; - ta_ctx->current_hash_stage = HASH_FINISH; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha1_digest(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha1 digest\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA1; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA1; - ta_ctx->current_hash_stage = HASH_DIGEST; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha1_finup(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha1 finup\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA1; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA1; - ta_ctx->current_hash_stage = HASH_FINUP_DATA; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_md5_init(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing md5 init\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = MD5; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_MD5; - ta_ctx->current_hash_stage = HASH_INIT; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_md5_update(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing md5 update\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = MD5; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_MD5; - ta_ctx->current_hash_stage = HASH_UPDATE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_md5_final(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing md5 final\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = MD5; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_MD5; - ta_ctx->current_hash_stage = HASH_FINISH; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_md5_digest(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing md5 digest\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = MD5; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_MD5; - ta_ctx->current_hash_stage = HASH_DIGEST; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_md5_finup(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing md5 finup\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = MD5; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_MD5; - ta_ctx->current_hash_stage = HASH_FINUP_DATA; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha224_init(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha224 init\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA224; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA224; - ta_ctx->current_hash_stage = HASH_INIT; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha224_update(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha224 update\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA224; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA224; - ta_ctx->current_hash_stage = HASH_UPDATE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha224_final(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha224 final\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA224; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA224; - ta_ctx->current_hash_stage = HASH_FINISH; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha224_digest(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha224 digest\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA224; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA224; - ta_ctx->current_hash_stage = HASH_DIGEST; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha224_finup(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha224 finup\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA224; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA224; - ta_ctx->current_hash_stage = HASH_FINUP_DATA; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha256_init(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha256 init\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA256; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA256; - ta_ctx->current_hash_stage = HASH_INIT; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha256_update(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha256 update\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA256; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA256; - ta_ctx->current_hash_stage = HASH_UPDATE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha256_final(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha256 final\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA256; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA256; - ta_ctx->current_hash_stage = HASH_FINISH; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha256_digest(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha256 digest\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA256; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA256; - ta_ctx->current_hash_stage = HASH_DIGEST; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_sha256_finup(struct ahash_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - - pr_debug("sep - doing sha256 finup\n"); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = SHA256; - ta_ctx->current_hash_req = req; - ta_ctx->current_cypher_req = NULL; - ta_ctx->hash_opmode = SEP_HASH_SHA256; - ta_ctx->current_hash_stage = HASH_FINUP_DATA; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_crypto_init(struct crypto_tfm *tfm) -{ - const char *alg_name = crypto_tfm_alg_name(tfm); - - if (alg_name == NULL) - pr_debug("sep_crypto_init alg is NULL\n"); - else - pr_debug("sep_crypto_init alg is %s\n", alg_name); - - tfm->crt_ablkcipher.reqsize = sizeof(struct this_task_ctx); - return 0; -} - -static void sep_crypto_exit(struct crypto_tfm *tfm) -{ - pr_debug("sep_crypto_exit\n"); -} - -static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int keylen) -{ - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx(tfm); - - pr_debug("sep aes setkey\n"); - - pr_debug("tfm is %p sctx is %p\n", tfm, sctx); - switch (keylen) { - case SEP_AES_KEY_128_SIZE: - sctx->aes_key_size = AES_128; - break; - case SEP_AES_KEY_192_SIZE: - sctx->aes_key_size = AES_192; - break; - case SEP_AES_KEY_256_SIZE: - sctx->aes_key_size = AES_256; - break; - case SEP_AES_KEY_512_SIZE: - sctx->aes_key_size = AES_512; - break; - default: - pr_debug("invalid sep aes key size %x\n", - keylen); - return -EINVAL; - } - - memset(&sctx->key.aes, 0, sizeof(u32) * - SEP_AES_MAX_KEY_SIZE_WORDS); - memcpy(&sctx->key.aes, key, keylen); - sctx->keylen = keylen; - /* Indicate to encrypt/decrypt function to send key to SEP */ - sctx->key_sent = 0; - - return 0; -} - -static int sep_aes_ecb_encrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - - pr_debug("sep - doing aes ecb encrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = AES_ECB; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->aes_encmode = SEP_AES_ENCRYPT; - ta_ctx->aes_opmode = SEP_AES_ECB; - ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_aes_ecb_decrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - - pr_debug("sep - doing aes ecb decrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = AES_ECB; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->aes_encmode = SEP_AES_DECRYPT; - ta_ctx->aes_opmode = SEP_AES_ECB; - ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_aes_cbc_encrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); - - pr_debug("sep - doing aes cbc encrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - pr_debug("tfm is %p sctx is %p and ta_ctx is %p\n", - crypto_ablkcipher_reqtfm(req), sctx, ta_ctx); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = AES_CBC; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->aes_encmode = SEP_AES_ENCRYPT; - ta_ctx->aes_opmode = SEP_AES_CBC; - ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_aes_cbc_decrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); - - pr_debug("sep - doing aes cbc decrypt\n"); - - pr_debug("tfm is %p sctx is %p and ta_ctx is %p\n", - crypto_ablkcipher_reqtfm(req), sctx, ta_ctx); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = AES_CBC; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->aes_encmode = SEP_AES_DECRYPT; - ta_ctx->aes_opmode = SEP_AES_CBC; - ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int keylen) -{ - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx(tfm); - struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm); - u32 *flags = &ctfm->crt_flags; - - pr_debug("sep des setkey\n"); - - switch (keylen) { - case DES_KEY_SIZE: - sctx->des_nbr_keys = DES_KEY_1; - break; - case DES_KEY_SIZE * 2: - sctx->des_nbr_keys = DES_KEY_2; - break; - case DES_KEY_SIZE * 3: - sctx->des_nbr_keys = DES_KEY_3; - break; - default: - pr_debug("invalid key size %x\n", - keylen); - return -EINVAL; - } - - if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY) && - (sep_weak_key(key, keylen))) { - - *flags |= CRYPTO_TFM_RES_WEAK_KEY; - pr_debug("weak key\n"); - return -EINVAL; - } - - memset(&sctx->key.des, 0, sizeof(struct sep_des_key)); - memcpy(&sctx->key.des.key1, key, keylen); - sctx->keylen = keylen; - /* Indicate to encrypt/decrypt function to send key to SEP */ - sctx->key_sent = 0; - - return 0; -} - -static int sep_des_ebc_encrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - - pr_debug("sep - doing des ecb encrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = DES_ECB; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->des_encmode = SEP_DES_ENCRYPT; - ta_ctx->des_opmode = SEP_DES_ECB; - ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_des_ebc_decrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - - pr_debug("sep - doing des ecb decrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = DES_ECB; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->des_encmode = SEP_DES_DECRYPT; - ta_ctx->des_opmode = SEP_DES_ECB; - ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_des_cbc_encrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - - pr_debug("sep - doing des cbc encrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = DES_CBC; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->des_encmode = SEP_DES_ENCRYPT; - ta_ctx->des_opmode = SEP_DES_CBC; - ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static int sep_des_cbc_decrypt(struct ablkcipher_request *req) -{ - int error; - int error1; - struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - - pr_debug("sep - doing des ecb decrypt\n"); - - /* Clear out task context */ - memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - - ta_ctx->sep_used = sep_dev; - ta_ctx->current_request = DES_CBC; - ta_ctx->current_hash_req = NULL; - ta_ctx->current_cypher_req = req; - ta_ctx->des_encmode = SEP_DES_DECRYPT; - ta_ctx->des_opmode = SEP_DES_CBC; - ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; - ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; - - /* lock necessary so that only one entity touches the queues */ - spin_lock_irq(&queue_lock); - error = crypto_enqueue_request(&sep_queue, &req->base); - - if ((error != 0) && (error != -EINPROGRESS)) - pr_debug(" sep - crypto enqueue failed: %x\n", - error); - error1 = sep_submit_work(ta_ctx->sep_used->workqueue, - sep_dequeuer, (void *)&sep_queue); - if (error1) - pr_debug(" sep - workqueue submit failed: %x\n", - error1); - spin_unlock_irq(&queue_lock); - /* We return result of crypto enqueue */ - return error; -} - -static struct ahash_alg hash_algs[] = { -{ - .init = sep_sha1_init, - .update = sep_sha1_update, - .final = sep_sha1_final, - .digest = sep_sha1_digest, - .finup = sep_sha1_finup, - .halg = { - .digestsize = SHA1_DIGEST_SIZE, - .base = { - .cra_name = "sha1", - .cra_driver_name = "sha1-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = sep_hash_cra_init, - .cra_exit = sep_hash_cra_exit, - } - } -}, -{ - .init = sep_md5_init, - .update = sep_md5_update, - .final = sep_md5_final, - .digest = sep_md5_digest, - .finup = sep_md5_finup, - .halg = { - .digestsize = MD5_DIGEST_SIZE, - .base = { - .cra_name = "md5", - .cra_driver_name = "md5-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = sep_hash_cra_init, - .cra_exit = sep_hash_cra_exit, - } - } -}, -{ - .init = sep_sha224_init, - .update = sep_sha224_update, - .final = sep_sha224_final, - .digest = sep_sha224_digest, - .finup = sep_sha224_finup, - .halg = { - .digestsize = SHA224_DIGEST_SIZE, - .base = { - .cra_name = "sha224", - .cra_driver_name = "sha224-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA224_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = sep_hash_cra_init, - .cra_exit = sep_hash_cra_exit, - } - } -}, -{ - .init = sep_sha256_init, - .update = sep_sha256_update, - .final = sep_sha256_final, - .digest = sep_sha256_digest, - .finup = sep_sha256_finup, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, - .base = { - .cra_name = "sha256", - .cra_driver_name = "sha256-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA256_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = sep_hash_cra_init, - .cra_exit = sep_hash_cra_exit, - } - } -} -}; - -static struct crypto_alg crypto_algs[] = { -{ - .cra_name = "ecb(aes)", - .cra_driver_name = "ecb-aes-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = sep_crypto_init, - .cra_exit = sep_crypto_exit, - .cra_u.ablkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = sep_aes_setkey, - .encrypt = sep_aes_ecb_encrypt, - .decrypt = sep_aes_ecb_decrypt, - } -}, -{ - .cra_name = "cbc(aes)", - .cra_driver_name = "cbc-aes-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = sep_crypto_init, - .cra_exit = sep_crypto_exit, - .cra_u.ablkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = sep_aes_setkey, - .encrypt = sep_aes_cbc_encrypt, - .ivsize = AES_BLOCK_SIZE, - .decrypt = sep_aes_cbc_decrypt, - } -}, -{ - .cra_name = "ebc(des)", - .cra_driver_name = "ebc-des-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = sep_crypto_init, - .cra_exit = sep_crypto_exit, - .cra_u.ablkcipher = { - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .setkey = sep_des_setkey, - .encrypt = sep_des_ebc_encrypt, - .decrypt = sep_des_ebc_decrypt, - } -}, -{ - .cra_name = "cbc(des)", - .cra_driver_name = "cbc-des-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = sep_crypto_init, - .cra_exit = sep_crypto_exit, - .cra_u.ablkcipher = { - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .setkey = sep_des_setkey, - .encrypt = sep_des_cbc_encrypt, - .ivsize = DES_BLOCK_SIZE, - .decrypt = sep_des_cbc_decrypt, - } -}, -{ - .cra_name = "ebc(des3-ede)", - .cra_driver_name = "ebc-des3-ede-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = sep_crypto_init, - .cra_exit = sep_crypto_exit, - .cra_u.ablkcipher = { - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - .setkey = sep_des_setkey, - .encrypt = sep_des_ebc_encrypt, - .decrypt = sep_des_ebc_decrypt, - } -}, -{ - .cra_name = "cbc(des3-ede)", - .cra_driver_name = "cbc-des3--ede-sep", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sep_system_ctx), - .cra_alignmask = 0, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = sep_crypto_init, - .cra_exit = sep_crypto_exit, - .cra_u.ablkcipher = { - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - .setkey = sep_des_setkey, - .encrypt = sep_des_cbc_encrypt, - .decrypt = sep_des_cbc_decrypt, - } -} -}; - -int sep_crypto_setup(void) -{ - int err, i, j, k; - - tasklet_init(&sep_dev->finish_tasklet, sep_finish, - (unsigned long)sep_dev); - - crypto_init_queue(&sep_queue, SEP_QUEUE_LENGTH); - - sep_dev->workqueue = create_singlethread_workqueue( - "sep_crypto_workqueue"); - if (!sep_dev->workqueue) { - dev_warn(&sep_dev->pdev->dev, "cant create workqueue\n"); - return -ENOMEM; - } - - spin_lock_init(&queue_lock); - - err = 0; - for (i = 0; i < ARRAY_SIZE(hash_algs); i++) { - err = crypto_register_ahash(&hash_algs[i]); - if (err) - goto err_algs; - } - - err = 0; - for (j = 0; j < ARRAY_SIZE(crypto_algs); j++) { - err = crypto_register_alg(&crypto_algs[j]); - if (err) - goto err_crypto_algs; - } - - return err; - -err_algs: - for (k = 0; k < i; k++) - crypto_unregister_ahash(&hash_algs[k]); - destroy_workqueue(sep_dev->workqueue); - return err; - -err_crypto_algs: - for (k = 0; k < j; k++) - crypto_unregister_alg(&crypto_algs[k]); - goto err_algs; -} - -void sep_crypto_takedown(void) -{ - - int i; - - for (i = 0; i < ARRAY_SIZE(hash_algs); i++) - crypto_unregister_ahash(&hash_algs[i]); - for (i = 0; i < ARRAY_SIZE(crypto_algs); i++) - crypto_unregister_alg(&crypto_algs[i]); - - destroy_workqueue(sep_dev->workqueue); - tasklet_kill(&sep_dev->finish_tasklet); -} - -#endif diff --git a/drivers/staging/sep/sep_crypto.h b/drivers/staging/sep/sep_crypto.h deleted file mode 100644 index 155c3c9b87c2..000000000000 --- a/drivers/staging/sep/sep_crypto.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * - * sep_crypto.h - Crypto interface structures - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2010 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * 2011.02.22 Enable Kernel Crypto - * - */ - -/* Constants for SEP (from vendor) */ -#define SEP_START_MSG_TOKEN 0x02558808 - -#define SEP_DES_IV_SIZE_WORDS 2 -#define SEP_DES_IV_SIZE_BYTES (SEP_DES_IV_SIZE_WORDS * \ - sizeof(u32)) -#define SEP_DES_KEY_SIZE_WORDS 2 -#define SEP_DES_KEY_SIZE_BYTES (SEP_DES_KEY_SIZE_WORDS * \ - sizeof(u32)) -#define SEP_DES_BLOCK_SIZE 8 -#define SEP_DES_DUMMY_SIZE 16 - -#define SEP_DES_INIT_OPCODE 0x10 -#define SEP_DES_BLOCK_OPCODE 0x11 - -#define SEP_AES_BLOCK_SIZE_WORDS 4 -#define SEP_AES_BLOCK_SIZE_BYTES \ - (SEP_AES_BLOCK_SIZE_WORDS * sizeof(u32)) - -#define SEP_AES_DUMMY_BLOCK_SIZE 16 -#define SEP_AES_IV_SIZE_WORDS SEP_AES_BLOCK_SIZE_WORDS -#define SEP_AES_IV_SIZE_BYTES \ - (SEP_AES_IV_SIZE_WORDS * sizeof(u32)) - -#define SEP_AES_KEY_128_SIZE 16 -#define SEP_AES_KEY_192_SIZE 24 -#define SEP_AES_KEY_256_SIZE 32 -#define SEP_AES_KEY_512_SIZE 64 -#define SEP_AES_MAX_KEY_SIZE_WORDS 16 -#define SEP_AES_MAX_KEY_SIZE_BYTES \ - (SEP_AES_MAX_KEY_SIZE_WORDS * sizeof(u32)) - -#define SEP_AES_WRAP_MIN_SIZE 8 -#define SEP_AES_WRAP_MAX_SIZE 0x10000000 - -#define SEP_AES_WRAP_BLOCK_SIZE_WORDS 2 -#define SEP_AES_WRAP_BLOCK_SIZE_BYTES \ - (SEP_AES_WRAP_BLOCK_SIZE_WORDS * sizeof(u32)) - -#define SEP_AES_SECRET_RKEK1 0x1 -#define SEP_AES_SECRET_RKEK2 0x2 - -#define SEP_AES_INIT_OPCODE 0x2 -#define SEP_AES_BLOCK_OPCODE 0x3 -#define SEP_AES_FINISH_OPCODE 0x4 -#define SEP_AES_WRAP_OPCODE 0x6 -#define SEP_AES_UNWRAP_OPCODE 0x7 -#define SEP_AES_XTS_FINISH_OPCODE 0x8 - -#define SEP_HASH_RESULT_SIZE_WORDS 16 -#define SEP_MD5_DIGEST_SIZE_WORDS 4 -#define SEP_MD5_DIGEST_SIZE_BYTES \ - (SEP_MD5_DIGEST_SIZE_WORDS * sizeof(u32)) -#define SEP_SHA1_DIGEST_SIZE_WORDS 5 -#define SEP_SHA1_DIGEST_SIZE_BYTES \ - (SEP_SHA1_DIGEST_SIZE_WORDS * sizeof(u32)) -#define SEP_SHA224_DIGEST_SIZE_WORDS 7 -#define SEP_SHA224_DIGEST_SIZE_BYTES \ - (SEP_SHA224_DIGEST_SIZE_WORDS * sizeof(u32)) -#define SEP_SHA256_DIGEST_SIZE_WORDS 8 -#define SEP_SHA256_DIGEST_SIZE_BYTES \ - (SEP_SHA256_DIGEST_SIZE_WORDS * sizeof(u32)) -#define SEP_SHA384_DIGEST_SIZE_WORDS 12 -#define SEP_SHA384_DIGEST_SIZE_BYTES \ - (SEP_SHA384_DIGEST_SIZE_WORDS * sizeof(u32)) -#define SEP_SHA512_DIGEST_SIZE_WORDS 16 -#define SEP_SHA512_DIGEST_SIZE_BYTES \ - (SEP_SHA512_DIGEST_SIZE_WORDS * sizeof(u32)) -#define SEP_HASH_BLOCK_SIZE_WORDS 16 -#define SEP_HASH_BLOCK_SIZE_BYTES \ - (SEP_HASH_BLOCK_SIZE_WORDS * sizeof(u32)) -#define SEP_SHA2_BLOCK_SIZE_WORDS 32 -#define SEP_SHA2_BLOCK_SIZE_BYTES \ - (SEP_SHA2_BLOCK_SIZE_WORDS * sizeof(u32)) - -#define SEP_HASH_INIT_OPCODE 0x20 -#define SEP_HASH_UPDATE_OPCODE 0x21 -#define SEP_HASH_FINISH_OPCODE 0x22 -#define SEP_HASH_SINGLE_OPCODE 0x23 - -#define SEP_HOST_ERROR 0x0b000000 -#define SEP_OK 0x0 -#define SEP_INVALID_START (SEP_HOST_ERROR + 0x3) -#define SEP_WRONG_OPCODE (SEP_HOST_ERROR + 0x1) - -#define SEP_TRANSACTION_WAIT_TIME 5 - -#define SEP_QUEUE_LENGTH 2 -/* Macros */ -#ifndef __LITTLE_ENDIAN -#define CHG_ENDIAN(val) \ - (((val) >> 24) | \ - (((val) & 0x00FF0000) >> 8) | \ - (((val) & 0x0000FF00) << 8) | \ - (((val) & 0x000000FF) << 24)) -#else -#define CHG_ENDIAN(val) val -#endif -/* Enums for SEP (from vendor) */ -enum des_numkey { - DES_KEY_1 = 1, - DES_KEY_2 = 2, - DES_KEY_3 = 3, - SEP_NUMKEY_OPTIONS, - SEP_NUMKEY_LAST = 0x7fffffff, -}; - -enum des_enc_mode { - SEP_DES_ENCRYPT = 0, - SEP_DES_DECRYPT = 1, - SEP_DES_ENC_OPTIONS, - SEP_DES_ENC_LAST = 0x7fffffff, -}; - -enum des_op_mode { - SEP_DES_ECB = 0, - SEP_DES_CBC = 1, - SEP_OP_OPTIONS, - SEP_OP_LAST = 0x7fffffff, -}; - -enum aes_keysize { - AES_128 = 0, - AES_192 = 1, - AES_256 = 2, - AES_512 = 3, - AES_SIZE_OPTIONS, - AEA_SIZE_LAST = 0x7FFFFFFF, -}; - -enum aes_enc_mode { - SEP_AES_ENCRYPT = 0, - SEP_AES_DECRYPT = 1, - SEP_AES_ENC_OPTIONS, - SEP_AES_ENC_LAST = 0x7FFFFFFF, -}; - -enum aes_op_mode { - SEP_AES_ECB = 0, - SEP_AES_CBC = 1, - SEP_AES_MAC = 2, - SEP_AES_CTR = 3, - SEP_AES_XCBC = 4, - SEP_AES_CMAC = 5, - SEP_AES_XTS = 6, - SEP_AES_OP_OPTIONS, - SEP_AES_OP_LAST = 0x7FFFFFFF, -}; - -enum hash_op_mode { - SEP_HASH_SHA1 = 0, - SEP_HASH_SHA224 = 1, - SEP_HASH_SHA256 = 2, - SEP_HASH_SHA384 = 3, - SEP_HASH_SHA512 = 4, - SEP_HASH_MD5 = 5, - SEP_HASH_OPTIONS, - SEP_HASH_LAST_MODE = 0x7FFFFFFF, -}; - -/* Structures for SEP (from vendor) */ -struct sep_des_internal_key { - u32 key1[SEP_DES_KEY_SIZE_WORDS]; - u32 key2[SEP_DES_KEY_SIZE_WORDS]; - u32 key3[SEP_DES_KEY_SIZE_WORDS]; -}; - -struct sep_des_internal_context { - u32 iv_context[SEP_DES_IV_SIZE_WORDS]; - struct sep_des_internal_key context_key; - enum des_numkey nbr_keys; - enum des_enc_mode encryption; - enum des_op_mode operation; - u8 dummy_block[SEP_DES_DUMMY_SIZE]; -}; - -struct sep_des_private_context { - u32 valid_tag; - u32 iv; - u8 ctx_buf[sizeof(struct sep_des_internal_context)]; -}; - -/* This is the structure passed to SEP via msg area */ -struct sep_des_key { - u32 key1[SEP_DES_KEY_SIZE_WORDS]; - u32 key2[SEP_DES_KEY_SIZE_WORDS]; - u32 key3[SEP_DES_KEY_SIZE_WORDS]; - u32 pad[SEP_DES_KEY_SIZE_WORDS]; -}; - -struct sep_aes_internal_context { - u32 aes_ctx_iv[SEP_AES_IV_SIZE_WORDS]; - u32 aes_ctx_key[SEP_AES_MAX_KEY_SIZE_WORDS / 2]; - enum aes_keysize keysize; - enum aes_enc_mode encmode; - enum aes_op_mode opmode; - u8 secret_key; - u32 no_add_blocks; - u32 last_block_size; - u32 last_block[SEP_AES_BLOCK_SIZE_WORDS]; - u32 prev_iv[SEP_AES_BLOCK_SIZE_WORDS]; - u32 remaining_size; - union { - struct { - u32 dkey1[SEP_AES_BLOCK_SIZE_WORDS]; - u32 dkey2[SEP_AES_BLOCK_SIZE_WORDS]; - u32 dkey3[SEP_AES_BLOCK_SIZE_WORDS]; - } cmac_data; - struct { - u32 xts_key[SEP_AES_MAX_KEY_SIZE_WORDS / 2]; - u32 temp1[SEP_AES_BLOCK_SIZE_WORDS]; - u32 temp2[SEP_AES_BLOCK_SIZE_WORDS]; - } xtx_data; - } s_data; - u8 dummy_block[SEP_AES_DUMMY_BLOCK_SIZE]; -}; - -struct sep_aes_private_context { - u32 valid_tag; - u32 aes_iv; - u32 op_mode; - u8 cbuff[sizeof(struct sep_aes_internal_context)]; -}; - -struct sep_hash_internal_context { - u32 hash_result[SEP_HASH_RESULT_SIZE_WORDS]; - enum hash_op_mode hash_opmode; - u32 previous_data[SEP_SHA2_BLOCK_SIZE_WORDS]; - u16 prev_update_bytes; - u32 total_proc_128bit[4]; - u16 op_mode_block_size; - u8 dummy_aes_block[SEP_AES_DUMMY_BLOCK_SIZE]; -}; - -struct sep_hash_private_context { - u32 valid_tag; - u32 iv; - u8 internal_context[sizeof(struct sep_hash_internal_context)]; -}; - -union key_t { - struct sep_des_key des; - u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS]; -}; - -/* Context structures for crypto API */ -/** - * Structure for this current task context - * This same structure is used for both hash - * and crypt in order to reduce duplicate code - * for stuff that is done for both hash operations - * and crypto operations. We cannot trust that the - * system context is not pulled out from under - * us during operation to operation, so all - * critical stuff such as data pointers must - * be in in a context that is exclusive for this - * particular task at hand. - */ -struct this_task_ctx { - struct sep_device *sep_used; - u32 done; - unsigned char iv[100]; - enum des_enc_mode des_encmode; - enum des_op_mode des_opmode; - enum aes_enc_mode aes_encmode; - enum aes_op_mode aes_opmode; - u32 init_opcode; - u32 block_opcode; - size_t data_length; - size_t ivlen; - struct ablkcipher_walk walk; - int i_own_sep; /* Do I have custody of the sep? */ - struct sep_call_status call_status; - struct build_dcb_struct_kernel dcb_input_data; - struct sep_dma_context *dma_ctx; - void *dmatables_region; - size_t nbytes; - struct sep_dcblock *dcb_region; - struct sep_queue_info *queue_elem; - int msg_len_words; - unsigned char msg[SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES]; - void *msgptr; - struct scatterlist *src_sg; - struct scatterlist *dst_sg; - struct scatterlist *src_sg_hold; - struct scatterlist *dst_sg_hold; - struct ahash_request *current_hash_req; - struct ablkcipher_request *current_cypher_req; - enum type_of_request current_request; - int digest_size_words; - int digest_size_bytes; - int block_size_words; - int block_size_bytes; - enum hash_op_mode hash_opmode; - enum hash_stage current_hash_stage; - /** - * Not that this is a pointer. The are_we_done_yet variable is - * allocated by the task function. This way, even if the kernel - * crypto infrastructure has grabbed the task structure out from - * under us, the task function can still see this variable. - */ - int *are_we_done_yet; - unsigned long end_time; - }; - -struct sep_system_ctx { - union key_t key; - size_t keylen; - int key_sent; - enum des_numkey des_nbr_keys; - enum aes_keysize aes_key_size; - unsigned long end_time; - struct sep_des_private_context des_private_ctx; - struct sep_aes_private_context aes_private_ctx; - struct sep_hash_private_context hash_private_ctx; - }; - -/* work queue structures */ -struct sep_work_struct { - struct work_struct work; - void (*callback)(void *); - void *data; - }; - -/* Functions */ -int sep_crypto_setup(void); -void sep_crypto_takedown(void); diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h deleted file mode 100644 index bf56c06662fd..000000000000 --- a/drivers/staging/sep/sep_dev.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef __SEP_DEV_H__ -#define __SEP_DEV_H__ - -/* - * - * sep_dev.h - Security Processor Device Structures - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2011 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES - * 2010.09.14 upgrade to Medfield - * 2011.02.22 enable kernel crypto - */ - -struct sep_device { - /* pointer to pci dev */ - struct pci_dev *pdev; - - /* character device file */ - struct cdev sep_cdev; - - /* devices (using misc dev) */ - struct miscdevice miscdev_sep; - - /* major / minor numbers of device */ - dev_t sep_devno; - /* guards command sent counter */ - spinlock_t snd_rply_lck; - /* guards driver memory usage in fastcall if */ - struct semaphore sep_doublebuf; - - /* flags to indicate use and lock status of sep */ - u32 pid_doing_transaction; - unsigned long in_use_flags; - - /* address of the shared memory allocated during init for SEP driver - (coherent alloc) */ - dma_addr_t shared_bus; - size_t shared_size; - void *shared_addr; - - /* start address of the access to the SEP registers from driver */ - dma_addr_t reg_physical_addr; - dma_addr_t reg_physical_end; - void __iomem *reg_addr; - - /* wait queue heads of the driver */ - wait_queue_head_t event_interrupt; - wait_queue_head_t event_transactions; - - struct list_head sep_queue_status; - u32 sep_queue_num; - spinlock_t sep_queue_lock; - - /* Is this in use? */ - u32 in_use; - - /* indicates whether power save is set up */ - u32 power_save_setup; - - /* Power state */ - u32 power_state; - - /* transaction counter that coordinates the - transactions between SEP and HOST */ - unsigned long send_ct; - /* counter for the messages from sep */ - unsigned long reply_ct; - - /* The following are used for kernel crypto client requests */ - u32 in_kernel; /* Set for kernel client request */ - struct tasklet_struct finish_tasklet; - enum type_of_request current_request; - enum hash_stage current_hash_stage; - struct ahash_request *current_hash_req; - struct ablkcipher_request *current_cypher_req; - struct this_task_ctx *ta_ctx; - struct workqueue_struct *workqueue; -}; - -extern struct sep_device *sep_dev; - -/** - * SEP message header for a transaction - * @reserved: reserved memory (two words) - * @token: SEP message token - * @msg_len: message length - * @opcpde: message opcode - */ -struct sep_msgarea_hdr { - u32 reserved[2]; - u32 token; - u32 msg_len; - u32 opcode; -}; - -/** - * sep_queue_data - data to be maintained in status queue for a transaction - * @opcode : transaction opcode - * @size : message size - * @pid: owner process - * @name: owner process name - */ -struct sep_queue_data { - u32 opcode; - u32 size; - s32 pid; - u8 name[TASK_COMM_LEN]; -}; - -/** sep_queue_info - maintains status info of all transactions - * @list: head of list - * @sep_queue_data : data for transaction - */ -struct sep_queue_info { - struct list_head list; - struct sep_queue_data data; -}; - -static inline void sep_write_reg(struct sep_device *dev, int reg, u32 value) -{ - void __iomem *addr = dev->reg_addr + reg; - writel(value, addr); -} - -static inline u32 sep_read_reg(struct sep_device *dev, int reg) -{ - void __iomem *addr = dev->reg_addr + reg; - return readl(addr); -} - -/* wait for SRAM write complete(indirect write */ -static inline void sep_wait_sram_write(struct sep_device *dev) -{ - u32 reg_val; - - do { - reg_val = sep_read_reg(dev, HW_SRAM_DATA_READY_REG_ADDR); - } while (!(reg_val & 1)); -} - - -#endif diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h deleted file mode 100644 index 7ee1c3bf17d7..000000000000 --- a/drivers/staging/sep/sep_driver_api.h +++ /dev/null @@ -1,402 +0,0 @@ -/* - * - * sep_driver_api.h - Security Processor Driver api definitions - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2011 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2010.09.14 Upgrade to Medfield - * 2011.02.22 Enable kernel crypto - * - */ - -#ifndef __SEP_DRIVER_API_H__ -#define __SEP_DRIVER_API_H__ - -/* Type of request from device */ -#define SEP_DRIVER_SRC_REPLY 1 -#define SEP_DRIVER_SRC_REQ 2 -#define SEP_DRIVER_SRC_PRINTF 3 - -/* Power state */ -#define SEP_DRIVER_POWERON 1 -#define SEP_DRIVER_POWEROFF 2 - -/* Following enums are used only for kernel crypto api */ -enum type_of_request { - NO_REQUEST, - AES_CBC, - AES_ECB, - DES_CBC, - DES_ECB, - DES3_ECB, - DES3_CBC, - SHA1, - MD5, - SHA224, - SHA256 - }; - -enum hash_stage { - HASH_INIT, - HASH_UPDATE, - HASH_FINISH, - HASH_DIGEST, - HASH_FINUP_DATA, - HASH_FINUP_FINISH -}; - -/* - structure that represents DCB -*/ -struct sep_dcblock { - /* physical address of the first input mlli */ - u32 input_mlli_address; - /* num of entries in the first input mlli */ - u32 input_mlli_num_entries; - /* size of data in the first input mlli */ - u32 input_mlli_data_size; - /* physical address of the first output mlli */ - u32 output_mlli_address; - /* num of entries in the first output mlli */ - u32 output_mlli_num_entries; - /* size of data in the first output mlli */ - u32 output_mlli_data_size; - /* pointer to the output virtual tail */ - aligned_u64 out_vr_tail_pt; - /* size of tail data */ - u32 tail_data_size; - /* input tail data array */ - u8 tail_data[68]; -}; - -/* - command structure for building dcb block (currently for ext app only) -*/ -struct build_dcb_struct { - /* address value of the data in */ - aligned_u64 app_in_address; - /* size of data in */ - u32 data_in_size; - /* address of the data out */ - aligned_u64 app_out_address; - /* the size of the block of the operation - if needed, - every table will be modulo this parameter */ - u32 block_size; - /* the size of the block of the operation - if needed, - every table will be modulo this parameter */ - u32 tail_block_size; - - /* which application calls the driver DX or applet */ - u32 is_applet; -}; - -/* - command structure for building dcb block for kernel crypto -*/ -struct build_dcb_struct_kernel { - /* address value of the data in */ - void *app_in_address; - /* size of data in */ - ssize_t data_in_size; - /* address of the data out */ - void *app_out_address; - /* the size of the block of the operation - if needed, - every table will be modulo this parameter */ - u32 block_size; - /* the size of the block of the operation - if needed, - every table will be modulo this parameter */ - u32 tail_block_size; - - /* which application calls the driver DX or applet */ - u32 is_applet; - - struct scatterlist *src_sg; - struct scatterlist *dst_sg; -}; - -/** - * @struct sep_dma_map - * - * Structure that contains all information needed for mapping the user pages - * or kernel buffers for dma operations - * - * - */ -struct sep_dma_map { - /* mapped dma address */ - dma_addr_t dma_addr; - /* size of the mapped data */ - size_t size; -}; - -struct sep_dma_resource { - /* array of pointers to the pages that represent - input data for the synchronic DMA action */ - struct page **in_page_array; - - /* array of pointers to the pages that represent out - data for the synchronic DMA action */ - struct page **out_page_array; - - /* number of pages in the sep_in_page_array */ - u32 in_num_pages; - - /* number of pages in the sep_out_page_array */ - u32 out_num_pages; - - /* map array of the input data */ - struct sep_dma_map *in_map_array; - - /* map array of the output data */ - struct sep_dma_map *out_map_array; - - /* number of entries of the input mapp array */ - u32 in_map_num_entries; - - /* number of entries of the output mapp array */ - u32 out_map_num_entries; - - /* Scatter list for kernel operations */ - struct scatterlist *src_sg; - struct scatterlist *dst_sg; -}; - - -/* command struct for translating rar handle to bus address - and setting it at predefined location */ -struct rar_hndl_to_bus_struct { - - /* rar handle */ - aligned_u64 rar_handle; -}; - -/* - structure that represent one entry in the DMA LLI table -*/ -struct sep_lli_entry { - /* physical address */ - u32 bus_address; - - /* block size */ - u32 block_size; -}; - -/* - * header format for each fastcall write operation - */ -struct sep_fastcall_hdr { - u32 magic; - u32 secure_dma; - u32 msg_len; - u32 num_dcbs; -}; - -/* - * structure used in file pointer's private data field - * to track the status of the calls to the various - * driver interface - */ -struct sep_call_status { - unsigned long status; -}; - -/* - * format of dma context buffer used to store all DMA-related - * context information of a particular transaction - */ -struct sep_dma_context { - /* number of data control blocks */ - u32 nr_dcb_creat; - /* number of the lli tables created in the current transaction */ - u32 num_lli_tables_created; - /* size of currently allocated dma tables region */ - u32 dmatables_len; - /* size of input data */ - u32 input_data_len; - /* secure dma use (for imr memory restricted area in output) */ - bool secure_dma; - struct sep_dma_resource dma_res_arr[SEP_MAX_NUM_SYNC_DMA_OPS]; - /* Scatter gather for kernel crypto */ - struct scatterlist *src_sg; - struct scatterlist *dst_sg; -}; - -/* - * format for file pointer's private_data field - */ -struct sep_private_data { - struct sep_queue_info *my_queue_elem; - struct sep_device *device; - struct sep_call_status call_status; - struct sep_dma_context *dma_ctx; -}; - - -/* Functions used by sep_crypto */ - -/** - * sep_queue_status_remove - Removes transaction from status queue - * @sep: SEP device - * @sep_queue_info: pointer to status queue - * - * This function will removes information about transaction from the queue. - */ -void sep_queue_status_remove(struct sep_device *sep, - struct sep_queue_info **queue_elem); -/** - * sep_queue_status_add - Adds transaction to status queue - * @sep: SEP device - * @opcode: transaction opcode - * @size: input data size - * @pid: pid of current process - * @name: current process name - * @name_len: length of name (current process) - * - * This function adds information about about transaction started to the status - * queue. - */ -struct sep_queue_info *sep_queue_status_add( - struct sep_device *sep, - u32 opcode, - u32 size, - u32 pid, - u8 *name, size_t name_len); - -/** - * sep_create_dcb_dmatables_context_kernel - Creates DCB & MLLI/DMA table context - * for kernel crypto - * @sep: SEP device - * @dcb_region: DCB region buf to create for current transaction - * @dmatables_region: MLLI/DMA tables buf to create for current transaction - * @dma_ctx: DMA context buf to create for current transaction - * @user_dcb_args: User arguments for DCB/MLLI creation - * @num_dcbs: Number of DCBs to create - */ -int sep_create_dcb_dmatables_context_kernel(struct sep_device *sep, - struct sep_dcblock **dcb_region, - void **dmatables_region, - struct sep_dma_context **dma_ctx, - const struct build_dcb_struct_kernel *dcb_data, - const u32 num_dcbs); - -/** - * sep_activate_dcb_dmatables_context - Takes DCB & DMA tables - * contexts into use - * @sep: SEP device - * @dcb_region: DCB region copy - * @dmatables_region: MLLI/DMA tables copy - * @dma_ctx: DMA context for current transaction - */ -ssize_t sep_activate_dcb_dmatables_context(struct sep_device *sep, - struct sep_dcblock **dcb_region, - void **dmatables_region, - struct sep_dma_context *dma_ctx); - -/** - * sep_prepare_input_output_dma_table_in_dcb - prepare control blocks - * @app_in_address: unsigned long; for data buffer in (user space) - * @app_out_address: unsigned long; for data buffer out (user space) - * @data_in_size: u32; for size of data - * @block_size: u32; for block size - * @tail_block_size: u32; for size of tail block - * @isapplet: bool; to indicate external app - * @is_kva: bool; kernel buffer; only used for kernel crypto module - * @secure_dma; indicates whether this is secure_dma using IMR - * - * This function prepares the linked DMA tables and puts the - * address for the linked list of tables inta a DCB (data control - * block) the address of which is known by the SEP hardware - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, - unsigned long app_in_address, - unsigned long app_out_address, - u32 data_in_size, - u32 block_size, - u32 tail_block_size, - bool isapplet, - bool is_kva, - bool secure_dma, - struct sep_dcblock *dcb_region, - void **dmatables_region, - struct sep_dma_context **dma_ctx, - struct scatterlist *src_sg, - struct scatterlist *dst_sg); - -/** - * sep_free_dma_table_data_handler - free DMA table - * @sep: pointer to struct sep_device - * @dma_ctx: dma context - * - * Handles the request to free DMA table for synchronic actions - */ -int sep_free_dma_table_data_handler(struct sep_device *sep, - struct sep_dma_context **dma_ctx); -/** - * sep_send_command_handler - kick off a command - * @sep: SEP being signalled - * - * This function raises interrupt to SEP that signals that is has a new - * command from the host - * - * Note that this function does fall under the ioctl lock - */ -int sep_send_command_handler(struct sep_device *sep); - -/** - * sep_wait_transaction - Used for synchronizing transactions - * @sep: SEP device - */ -int sep_wait_transaction(struct sep_device *sep); - -/** - * IOCTL command defines - */ -/* magic number 1 of the sep IOCTL command */ -#define SEP_IOC_MAGIC_NUMBER 's' - -/* sends interrupt to sep that message is ready */ -#define SEP_IOCSENDSEPCOMMAND \ - _IO(SEP_IOC_MAGIC_NUMBER, 0) - -/* end transaction command */ -#define SEP_IOCENDTRANSACTION \ - _IO(SEP_IOC_MAGIC_NUMBER, 15) - -#define SEP_IOCPREPAREDCB \ - _IOW(SEP_IOC_MAGIC_NUMBER, 35, struct build_dcb_struct) - -#define SEP_IOCFREEDCB \ - _IO(SEP_IOC_MAGIC_NUMBER, 36) - -struct sep_device; - -#define SEP_IOCPREPAREDCB_SECURE_DMA \ - _IOW(SEP_IOC_MAGIC_NUMBER, 38, struct build_dcb_struct) - -#define SEP_IOCFREEDCB_SECURE_DMA \ - _IO(SEP_IOC_MAGIC_NUMBER, 39) - -#endif diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h deleted file mode 100644 index 4b6e30743634..000000000000 --- a/drivers/staging/sep/sep_driver_config.h +++ /dev/null @@ -1,298 +0,0 @@ -/* - * - * sep_driver_config.h - Security Processor Driver configuration - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2011 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2010.06.26 Upgrade to Medfield - * 2011.02.22 Enable kernel crypto - * - */ - -#ifndef __SEP_DRIVER_CONFIG_H__ -#define __SEP_DRIVER_CONFIG_H__ - - -/*-------------------------------------- - DRIVER CONFIGURATION FLAGS - -------------------------------------*/ - -/* if flag is on , then the driver is running in polling and - not interrupt mode */ -#define SEP_DRIVER_POLLING_MODE 0 - -/* flag which defines if the shared area address should be - reconfigured (send to SEP anew) during init of the driver */ -#define SEP_DRIVER_RECONFIG_MESSAGE_AREA 0 - -/* the mode for running on the ARM1172 Evaluation platform (flag is 1) */ -#define SEP_DRIVER_ARM_DEBUG_MODE 0 - -/* Critical message area contents for sanity checking */ -#define SEP_START_MSG_TOKEN 0x02558808 -/*------------------------------------------- - INTERNAL DATA CONFIGURATION - -------------------------------------------*/ - -/* flag for the input array */ -#define SEP_DRIVER_IN_FLAG 0 - -/* flag for output array */ -#define SEP_DRIVER_OUT_FLAG 1 - -/* maximum number of entries in one LLI tables */ -#define SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP 31 - -/* minimum data size of the MLLI table */ -#define SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE 16 - -/* flag that signifies tah the lock is -currently held by the process (struct file) */ -#define SEP_DRIVER_OWN_LOCK_FLAG 1 - -/* flag that signifies tah the lock is currently NOT -held by the process (struct file) */ -#define SEP_DRIVER_DISOWN_LOCK_FLAG 0 - -/* indicates whether driver has mapped/unmapped shared area */ -#define SEP_REQUEST_DAEMON_MAPPED 1 -#define SEP_REQUEST_DAEMON_UNMAPPED 0 - -/*-------------------------------------------------------- - SHARED AREA memory total size is 36K - it is divided is following: - - SHARED_MESSAGE_AREA 8K } - } - STATIC_POOL_AREA 4K } MAPPED AREA ( 24 K) - } - DATA_POOL_AREA 12K } - - SYNCHRONIC_DMA_TABLES_AREA 29K - - placeholder until drver changes - FLOW_DMA_TABLES_AREA 4K - - SYSTEM_MEMORY_AREA 3k - - SYSTEM_MEMORY total size is 3k - it is divided as following: - - TIME_MEMORY_AREA 8B ------------------------------------------------------------*/ - -#define SEP_DEV_NAME "sep_sec_driver" -#define SEP_DEV_SINGLETON "sep_sec_singleton_driver" -#define SEP_DEV_DAEMON "sep_req_daemon_driver" - - -/* - the minimum length of the message - includes 2 reserved fields - at the start, then token, message size and opcode fields. all dwords -*/ -#define SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES (5*sizeof(u32)) - -/* - the maximum length of the message - the rest of the message shared - area will be dedicated to the dma lli tables -*/ -#define SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES (8 * 1024) - -/* the size of the message shared area in pages */ -#define SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES (8 * 1024) - -/* the size of the data pool static area in pages */ -#define SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES (4 * 1024) - -/* the size of the data pool shared area size in pages */ -#define SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES (16 * 1024) - -/* the size of the message shared area in pages */ -#define SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES (1024 * 29) - -/* Placeholder until driver changes */ -#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES (1024 * 4) - -/* system data (time, caller id etc') pool */ -#define SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES (1024 * 3) - -/* Offset of the sep printf buffer in the message area */ -#define SEP_DRIVER_PRINTF_OFFSET_IN_BYTES (5888) - -/* the size in bytes of the time memory */ -#define SEP_DRIVER_TIME_MEMORY_SIZE_IN_BYTES 8 - -/* the size in bytes of the RAR parameters memory */ -#define SEP_DRIVER_SYSTEM_RAR_MEMORY_SIZE_IN_BYTES 8 - -/* area size that is mapped - we map the MESSAGE AREA, STATIC POOL and - DATA POOL areas. area must be module 4k */ -#define SEP_DRIVER_MMMAP_AREA_SIZE (1024 * 28) - -/*----------------------------------------------- - offsets of the areas starting from the shared area start address -*/ - -/* message area offset */ -#define SEP_DRIVER_MESSAGE_AREA_OFFSET_IN_BYTES 0 - -/* static pool area offset */ -#define SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES \ - (SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES) - -/* data pool area offset */ -#define SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES \ - (SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES + \ - SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES) - -/* synchronic dma tables area offset */ -#define SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES \ - (SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + \ - SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) - -/* system memory offset in bytes */ -#define SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES \ - (SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + \ - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES) - -/* offset of the time area */ -#define SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES \ - (SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES) - -/* offset of the RAR area */ -#define SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES \ - (SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES + \ - SEP_DRIVER_TIME_MEMORY_SIZE_IN_BYTES) - -/* offset of the caller id area */ -#define SEP_CALLER_ID_OFFSET_BYTES \ - (SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES + \ - SEP_DRIVER_SYSTEM_RAR_MEMORY_SIZE_IN_BYTES) - -/* offset of the DCB area */ -#define SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES \ - (SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES + \ - 0x400) - -/* offset of the ext cache area */ -#define SEP_DRIVER_SYSTEM_EXT_CACHE_ADDR_OFFSET_IN_BYTES \ - SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES - -/* offset of the allocation data pointer area */ -#define SEP_DRIVER_DATA_POOL_ALLOCATION_OFFSET_IN_BYTES \ - (SEP_CALLER_ID_OFFSET_BYTES + \ - SEP_CALLER_ID_HASH_SIZE_IN_BYTES) - -/* the token that defines the start of time address */ -#define SEP_TIME_VAL_TOKEN 0x12345678 - -#define FAKE_RAR_SIZE (1024*1024) /* used only for mfld */ -/* DEBUG LEVEL MASKS */ - -/* size of the caller id hash (sha2) */ -#define SEP_CALLER_ID_HASH_SIZE_IN_BYTES 32 - -/* size of the caller id hash (sha2) in 32 bit words */ -#define SEP_CALLER_ID_HASH_SIZE_IN_WORDS 8 - -/* maximum number of entries in the caller id table */ -#define SEP_CALLER_ID_TABLE_NUM_ENTRIES 20 - -/* maximum number of symmetric operation (that require DMA resource) - per one message */ -#define SEP_MAX_NUM_SYNC_DMA_OPS 16 - -/* the token that defines the start of time address */ -#define SEP_RAR_VAL_TOKEN 0xABABABAB - -/* ioctl error that should be returned when trying - to realloc the cache/resident second time */ -#define SEP_ALREADY_INITIALIZED_ERR 12 - -/* bit that locks access to the shared area */ -#define SEP_TRANSACTION_STARTED_LOCK_BIT 0 - -/* bit that lock access to the poll - after send_command */ -#define SEP_WORKING_LOCK_BIT 1 - -/* the token that defines the static pool address address */ -#define SEP_STATIC_POOL_VAL_TOKEN 0xABBAABBA - -/* the token that defines the data pool pointers address */ -#define SEP_DATA_POOL_POINTERS_VAL_TOKEN 0xEDDEEDDE - -/* the token that defines the data pool pointers address */ -#define SEP_EXT_CACHE_ADDR_VAL_TOKEN 0xBABABABA - -/* Time limit for SEP to finish */ -#define WAIT_TIME 10 - -/* Delay for pm runtime suspend (reduces pm thrashing with bursty traffic */ -#define SUSPEND_DELAY 10 - -/* Number of delays to wait until scu boots after runtime resume */ -#define SCU_DELAY_MAX 50 - -/* Delay for each iteration (usec) wait for scu boots after runtime resume */ -#define SCU_DELAY_ITERATION 10 - - -/* - * Bits used in struct sep_call_status to check that - * driver's APIs are called in valid order - */ - -/* Bit offset which indicates status of sep_write() */ -#define SEP_FASTCALL_WRITE_DONE_OFFSET 0 - -/* Bit offset which indicates status of sep_mmap() */ -#define SEP_LEGACY_MMAP_DONE_OFFSET 1 - -/* Bit offset which indicates status of the SEP_IOCSENDSEPCOMMAND ioctl */ -#define SEP_LEGACY_SENDMSG_DONE_OFFSET 2 - -/* Bit offset which indicates status of sep_poll() */ -#define SEP_LEGACY_POLL_DONE_OFFSET 3 - -/* Bit offset which indicates status of the SEP_IOCENDTRANSACTION ioctl */ -#define SEP_LEGACY_ENDTRANSACTION_DONE_OFFSET 4 - -/* - * Used to limit number of concurrent processes - * allowed to allocate dynamic buffers in fastcall - * interface. - */ -#define SEP_DOUBLEBUF_USERS_LIMIT 3 - -/* Identifier for valid fastcall header */ -#define SEP_FC_MAGIC 0xFFAACCAA - -/* - * Used for enabling driver runtime power management. - * Useful for enabling/disabling it during performance - * testing - */ -#define SEP_ENABLE_RUNTIME_PM - -#endif /* SEP DRIVER CONFIG */ diff --git a/drivers/staging/sep/sep_driver_hw_defs.h b/drivers/staging/sep/sep_driver_hw_defs.h deleted file mode 100644 index a6a448170382..000000000000 --- a/drivers/staging/sep/sep_driver_hw_defs.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * sep_driver_hw_defs.h - Security Processor Driver hardware definitions - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2011 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2010.09.20 Upgrade to Medfield - * 2011.02.22 Enable kernel crypto - * - */ - -#ifndef SEP_DRIVER_HW_DEFS__H -#define SEP_DRIVER_HW_DEFS__H - -/*----------------------- */ -/* HW Registers Defines. */ -/* */ -/*---------------------- -*/ - - -/* cf registers */ -#define HW_HOST_IRR_REG_ADDR 0x0A00UL -#define HW_HOST_IMR_REG_ADDR 0x0A04UL -#define HW_HOST_ICR_REG_ADDR 0x0A08UL -#define HW_HOST_SEP_HOST_GPR0_REG_ADDR 0x0B00UL -#define HW_HOST_SEP_HOST_GPR1_REG_ADDR 0x0B04UL -#define HW_HOST_SEP_HOST_GPR2_REG_ADDR 0x0B08UL -#define HW_HOST_SEP_HOST_GPR3_REG_ADDR 0x0B0CUL -#define HW_HOST_HOST_SEP_GPR0_REG_ADDR 0x0B80UL -#define HW_HOST_HOST_SEP_GPR1_REG_ADDR 0x0B84UL -#define HW_HOST_HOST_SEP_GPR2_REG_ADDR 0x0B88UL -#define HW_HOST_HOST_SEP_GPR3_REG_ADDR 0x0B8CUL -#define HW_SRAM_DATA_READY_REG_ADDR 0x0F08UL - -#endif /* ifndef HW_DEFS */ diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c deleted file mode 100644 index 85fea5fc5e59..000000000000 --- a/drivers/staging/sep/sep_main.c +++ /dev/null @@ -1,4411 +0,0 @@ -/* - * - * sep_main.c - Security Processor Driver main group of functions - * - * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. - * Contributions(c) 2009-2011 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * 2010.09.14 Upgrade to Medfield - * 2011.01.21 Move to sep_main.c to allow for sep_crypto.c - * 2011.02.22 Enable kernel crypto operation - * - * Please note that this driver is based on information in the Discretix - * CryptoCell 5.2 Driver Implementation Guide; the Discretix CryptoCell 5.2 - * Integration Intel Medfield appendix; the Discretix CryptoCell 5.2 - * Linux Driver Integration Guide; and the Discretix CryptoCell 5.2 System - * Overview and Integration Guide. - */ -/* #define DEBUG */ -/* #define SEP_PERF_DEBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sep_driver_hw_defs.h" -#include "sep_driver_config.h" -#include "sep_driver_api.h" -#include "sep_dev.h" -#include "sep_crypto.h" - -#define CREATE_TRACE_POINTS -#include "sep_trace_events.h" - -/* - * Let's not spend cycles iterating over message - * area contents if debugging not enabled - */ -#ifdef DEBUG -#define sep_dump_message(sep) _sep_dump_message(sep) -#else -#define sep_dump_message(sep) -#endif - -/** - * Currently, there is only one SEP device per platform; - * In event platforms in the future have more than one SEP - * device, this will be a linked list - */ - -struct sep_device *sep_dev; - -/** - * sep_queue_status_remove - Removes transaction from status queue - * @sep: SEP device - * @sep_queue_info: pointer to status queue - * - * This function will remove information about transaction from the queue. - */ -void sep_queue_status_remove(struct sep_device *sep, - struct sep_queue_info **queue_elem) -{ - unsigned long lck_flags; - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_queue_status_remove\n", - current->pid); - - if (!queue_elem || !(*queue_elem)) { - dev_dbg(&sep->pdev->dev, "PID%d %s null\n", - current->pid, __func__); - return; - } - - spin_lock_irqsave(&sep->sep_queue_lock, lck_flags); - list_del(&(*queue_elem)->list); - sep->sep_queue_num--; - spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); - - kfree(*queue_elem); - *queue_elem = NULL; - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_queue_status_remove return\n", - current->pid); -} - -/** - * sep_queue_status_add - Adds transaction to status queue - * @sep: SEP device - * @opcode: transaction opcode - * @size: input data size - * @pid: pid of current process - * @name: current process name - * @name_len: length of name (current process) - * - * This function adds information about about transaction started to the status - * queue. - */ -struct sep_queue_info *sep_queue_status_add( - struct sep_device *sep, - u32 opcode, - u32 size, - u32 pid, - u8 *name, size_t name_len) -{ - unsigned long lck_flags; - struct sep_queue_info *my_elem = NULL; - - my_elem = kzalloc(sizeof(struct sep_queue_info), GFP_KERNEL); - - if (!my_elem) - return NULL; - - dev_dbg(&sep->pdev->dev, "[PID%d] kzalloc ok\n", current->pid); - - my_elem->data.opcode = opcode; - my_elem->data.size = size; - my_elem->data.pid = pid; - - if (name_len > TASK_COMM_LEN) - name_len = TASK_COMM_LEN; - - memcpy(&my_elem->data.name, name, name_len); - - spin_lock_irqsave(&sep->sep_queue_lock, lck_flags); - - list_add_tail(&my_elem->list, &sep->sep_queue_status); - sep->sep_queue_num++; - - spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); - - return my_elem; -} - -/** - * sep_allocate_dmatables_region - Allocates buf for the MLLI/DMA tables - * @sep: SEP device - * @dmatables_region: Destination pointer for the buffer - * @dma_ctx: DMA context for the transaction - * @table_count: Number of MLLI/DMA tables to create - * The buffer created will not work as-is for DMA operations, - * it needs to be copied over to the appropriate place in the - * shared area. - */ -static int sep_allocate_dmatables_region(struct sep_device *sep, - void **dmatables_region, - struct sep_dma_context *dma_ctx, - const u32 table_count) -{ - const size_t new_len = - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES - 1; - - void *tmp_region = NULL; - - dev_dbg(&sep->pdev->dev, "[PID%d] dma_ctx = 0x%p\n", - current->pid, dma_ctx); - dev_dbg(&sep->pdev->dev, "[PID%d] dmatables_region = 0x%p\n", - current->pid, dmatables_region); - - if (!dma_ctx || !dmatables_region) { - dev_warn(&sep->pdev->dev, - "[PID%d] dma context/region uninitialized\n", - current->pid); - return -EINVAL; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] newlen = 0x%08zX\n", - current->pid, new_len); - dev_dbg(&sep->pdev->dev, "[PID%d] oldlen = 0x%08X\n", current->pid, - dma_ctx->dmatables_len); - tmp_region = kzalloc(new_len + dma_ctx->dmatables_len, GFP_KERNEL); - if (!tmp_region) - return -ENOMEM; - - /* Were there any previous tables that need to be preserved ? */ - if (*dmatables_region) { - memcpy(tmp_region, *dmatables_region, dma_ctx->dmatables_len); - kfree(*dmatables_region); - *dmatables_region = NULL; - } - - *dmatables_region = tmp_region; - - dma_ctx->dmatables_len += new_len; - - return 0; -} - -/** - * sep_wait_transaction - Used for synchronizing transactions - * @sep: SEP device - */ -int sep_wait_transaction(struct sep_device *sep) -{ - int error = 0; - DEFINE_WAIT(wait); - - if (0 == test_and_set_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, - &sep->in_use_flags)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] no transactions, returning\n", - current->pid); - goto end_function_setpid; - } - - /* - * Looping needed even for exclusive waitq entries - * due to process wakeup latencies, previous process - * might have already created another transaction. - */ - for (;;) { - /* - * Exclusive waitq entry, so that only one process is - * woken up from the queue at a time. - */ - prepare_to_wait_exclusive(&sep->event_transactions, - &wait, - TASK_INTERRUPTIBLE); - if (0 == test_and_set_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, - &sep->in_use_flags)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] no transactions, breaking\n", - current->pid); - break; - } - dev_dbg(&sep->pdev->dev, - "[PID%d] transactions ongoing, sleeping\n", - current->pid); - schedule(); - dev_dbg(&sep->pdev->dev, "[PID%d] woken up\n", current->pid); - - if (signal_pending(current)) { - dev_dbg(&sep->pdev->dev, "[PID%d] received signal\n", - current->pid); - error = -EINTR; - goto end_function; - } - } -end_function_setpid: - /* - * The pid_doing_transaction indicates that this process - * now owns the facilities to perform a transaction with - * the SEP. While this process is performing a transaction, - * no other process who has the SEP device open can perform - * any transactions. This method allows more than one process - * to have the device open at any given time, which provides - * finer granularity for device utilization by multiple - * processes. - */ - /* Only one process is able to progress here at a time */ - sep->pid_doing_transaction = current->pid; - -end_function: - finish_wait(&sep->event_transactions, &wait); - - return error; -} - -/** - * sep_check_transaction_owner - Checks if current process owns transaction - * @sep: SEP device - */ -static inline int sep_check_transaction_owner(struct sep_device *sep) -{ - dev_dbg(&sep->pdev->dev, "[PID%d] transaction pid = %d\n", - current->pid, - sep->pid_doing_transaction); - - if ((sep->pid_doing_transaction == 0) || - (current->pid != sep->pid_doing_transaction)) { - return -EACCES; - } - - /* We own the transaction */ - return 0; -} - -#ifdef DEBUG - -/** - * sep_dump_message - dump the message that is pending - * @sep: SEP device - * This will only print dump if DEBUG is set; it does - * follow kernel debug print enabling - */ -static void _sep_dump_message(struct sep_device *sep) -{ - int count; - - u32 *p = sep->shared_addr; - - for (count = 0; count < 10 * 4; count += 4) - dev_dbg(&sep->pdev->dev, - "[PID%d] Word %d of the message is %x\n", - current->pid, count/4, *p++); -} - -#endif - -/** - * sep_map_and_alloc_shared_area -allocate shared block - * @sep: security processor - * @size: size of shared area - */ -static int sep_map_and_alloc_shared_area(struct sep_device *sep) -{ - sep->shared_addr = dma_alloc_coherent(&sep->pdev->dev, - sep->shared_size, - &sep->shared_bus, GFP_KERNEL); - - if (!sep->shared_addr) { - dev_dbg(&sep->pdev->dev, - "[PID%d] shared memory dma_alloc_coherent failed\n", - current->pid); - return -ENOMEM; - } - dev_dbg(&sep->pdev->dev, - "[PID%d] shared_addr %zx bytes @%p (bus %llx)\n", - current->pid, - sep->shared_size, sep->shared_addr, - (unsigned long long)sep->shared_bus); - return 0; -} - -/** - * sep_unmap_and_free_shared_area - free shared block - * @sep: security processor - */ -static void sep_unmap_and_free_shared_area(struct sep_device *sep) -{ - dma_free_coherent(&sep->pdev->dev, sep->shared_size, - sep->shared_addr, sep->shared_bus); -} - -#ifdef DEBUG - -/** - * sep_shared_bus_to_virt - convert bus/virt addresses - * @sep: pointer to struct sep_device - * @bus_address: address to convert - * - * Returns virtual address inside the shared area according - * to the bus address. - */ -static void *sep_shared_bus_to_virt(struct sep_device *sep, - dma_addr_t bus_address) -{ - return sep->shared_addr + (bus_address - sep->shared_bus); -} - -#endif - -/** - * sep_open - device open method - * @inode: inode of SEP device - * @filp: file handle to SEP device - * - * Open method for the SEP device. Called when userspace opens - * the SEP device node. - * - * Returns zero on success otherwise an error code. - */ -static int sep_open(struct inode *inode, struct file *filp) -{ - struct sep_device *sep; - struct sep_private_data *priv; - - dev_dbg(&sep_dev->pdev->dev, "[PID%d] open\n", current->pid); - - if (filp->f_flags & O_NONBLOCK) - return -ENOTSUPP; - - /* - * Get the SEP device structure and use it for the - * private_data field in filp for other methods - */ - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - sep = sep_dev; - priv->device = sep; - filp->private_data = priv; - - dev_dbg(&sep_dev->pdev->dev, "[PID%d] priv is 0x%p\n", - current->pid, priv); - - /* Anyone can open; locking takes place at transaction level */ - return 0; -} - -/** - * sep_free_dma_table_data_handler - free DMA table - * @sep: pointer to struct sep_device - * @dma_ctx: dma context - * - * Handles the request to free DMA table for synchronic actions - */ -int sep_free_dma_table_data_handler(struct sep_device *sep, - struct sep_dma_context **dma_ctx) -{ - int count; - int dcb_counter; - /* Pointer to the current dma_resource struct */ - struct sep_dma_resource *dma; - - dev_dbg(&sep->pdev->dev, - "[PID%d] sep_free_dma_table_data_handler\n", - current->pid); - - if (!dma_ctx || !(*dma_ctx)) { - /* No context or context already freed */ - dev_dbg(&sep->pdev->dev, - "[PID%d] no DMA context or context already freed\n", - current->pid); - - return 0; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] (*dma_ctx)->nr_dcb_creat 0x%x\n", - current->pid, - (*dma_ctx)->nr_dcb_creat); - - for (dcb_counter = 0; - dcb_counter < (*dma_ctx)->nr_dcb_creat; dcb_counter++) { - dma = &(*dma_ctx)->dma_res_arr[dcb_counter]; - - /* Unmap and free input map array */ - if (dma->in_map_array) { - for (count = 0; count < dma->in_num_pages; count++) { - dma_unmap_page(&sep->pdev->dev, - dma->in_map_array[count].dma_addr, - dma->in_map_array[count].size, - DMA_TO_DEVICE); - } - kfree(dma->in_map_array); - } - - /** - * Output is handled different. If - * this was a secure dma into restricted memory, - * then we skip this step altogether as restricted - * memory is not available to the o/s at all. - */ - if (!(*dma_ctx)->secure_dma && dma->out_map_array) { - for (count = 0; count < dma->out_num_pages; count++) { - dma_unmap_page(&sep->pdev->dev, - dma->out_map_array[count].dma_addr, - dma->out_map_array[count].size, - DMA_FROM_DEVICE); - } - kfree(dma->out_map_array); - } - - /* Free page cache for output */ - if (dma->in_page_array) { - for (count = 0; count < dma->in_num_pages; count++) { - flush_dcache_page(dma->in_page_array[count]); - page_cache_release(dma->in_page_array[count]); - } - kfree(dma->in_page_array); - } - - /* Again, we do this only for non secure dma */ - if (!(*dma_ctx)->secure_dma && dma->out_page_array) { - for (count = 0; count < dma->out_num_pages; count++) { - if (!PageReserved(dma->out_page_array[count])) - - SetPageDirty(dma-> - out_page_array[count]); - - flush_dcache_page(dma->out_page_array[count]); - page_cache_release(dma->out_page_array[count]); - } - kfree(dma->out_page_array); - } - - /** - * Note that here we use in_map_num_entries because we - * don't have a page array; the page array is generated - * only in the lock_user_pages, which is not called - * for kernel crypto, which is what the sg (scatter gather - * is used for exclusively) - */ - if (dma->src_sg) { - dma_unmap_sg(&sep->pdev->dev, dma->src_sg, - dma->in_map_num_entries, DMA_TO_DEVICE); - dma->src_sg = NULL; - } - - if (dma->dst_sg) { - dma_unmap_sg(&sep->pdev->dev, dma->dst_sg, - dma->in_map_num_entries, DMA_FROM_DEVICE); - dma->dst_sg = NULL; - } - - /* Reset all the values */ - dma->in_page_array = NULL; - dma->out_page_array = NULL; - dma->in_num_pages = 0; - dma->out_num_pages = 0; - dma->in_map_array = NULL; - dma->out_map_array = NULL; - dma->in_map_num_entries = 0; - dma->out_map_num_entries = 0; - } - - (*dma_ctx)->nr_dcb_creat = 0; - (*dma_ctx)->num_lli_tables_created = 0; - - kfree(*dma_ctx); - *dma_ctx = NULL; - - dev_dbg(&sep->pdev->dev, - "[PID%d] sep_free_dma_table_data_handler end\n", - current->pid); - - return 0; -} - -/** - * sep_end_transaction_handler - end transaction - * @sep: pointer to struct sep_device - * @dma_ctx: DMA context - * @call_status: Call status - * - * This API handles the end transaction request. - */ -static int sep_end_transaction_handler(struct sep_device *sep, - struct sep_dma_context **dma_ctx, - struct sep_call_status *call_status, - struct sep_queue_info **my_queue_elem) -{ - dev_dbg(&sep->pdev->dev, "[PID%d] ending transaction\n", current->pid); - - /* - * Extraneous transaction clearing would mess up PM - * device usage counters and SEP would get suspended - * just before we send a command to SEP in the next - * transaction - * */ - if (sep_check_transaction_owner(sep)) { - dev_dbg(&sep->pdev->dev, "[PID%d] not transaction owner\n", - current->pid); - return 0; - } - - /* Update queue status */ - sep_queue_status_remove(sep, my_queue_elem); - - /* Check that all the DMA resources were freed */ - if (dma_ctx) - sep_free_dma_table_data_handler(sep, dma_ctx); - - /* Reset call status for next transaction */ - if (call_status) - call_status->status = 0; - - /* Clear the message area to avoid next transaction reading - * sensitive results from previous transaction */ - memset(sep->shared_addr, 0, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - /* start suspend delay */ -#ifdef SEP_ENABLE_RUNTIME_PM - if (sep->in_use) { - sep->in_use = 0; - pm_runtime_mark_last_busy(&sep->pdev->dev); - pm_runtime_put_autosuspend(&sep->pdev->dev); - } -#endif - - clear_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags); - sep->pid_doing_transaction = 0; - - /* Now it's safe for next process to proceed */ - dev_dbg(&sep->pdev->dev, "[PID%d] waking up next transaction\n", - current->pid); - clear_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, &sep->in_use_flags); - wake_up(&sep->event_transactions); - - return 0; -} - -/** - * sep_release - close a SEP device - * @inode: inode of SEP device - * @filp: file handle being closed - * - * Called on the final close of a SEP device. - */ -static int sep_release(struct inode *inode, struct file *filp) -{ - struct sep_private_data * const private_data = filp->private_data; - struct sep_call_status *call_status = &private_data->call_status; - struct sep_device *sep = private_data->device; - struct sep_dma_context **dma_ctx = &private_data->dma_ctx; - struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; - - dev_dbg(&sep->pdev->dev, "[PID%d] release\n", current->pid); - - sep_end_transaction_handler(sep, dma_ctx, call_status, - my_queue_elem); - - kfree(filp->private_data); - - return 0; -} - -/** - * sep_mmap - maps the shared area to user space - * @filp: pointer to struct file - * @vma: pointer to vm_area_struct - * - * Called on an mmap of our space via the normal SEP device - */ -static int sep_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct sep_private_data * const private_data = filp->private_data; - struct sep_call_status *call_status = &private_data->call_status; - struct sep_device *sep = private_data->device; - struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; - dma_addr_t bus_addr; - unsigned long error = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_mmap\n", current->pid); - - /* Set the transaction busy (own the device) */ - /* - * Problem for multithreaded applications is that here we're - * possibly going to sleep while holding a write lock on - * current->mm->mmap_sem, which will cause deadlock for ongoing - * transaction trying to create DMA tables - */ - error = sep_wait_transaction(sep); - if (error) - /* Interrupted by signal, don't clear transaction */ - goto end_function; - - /* Clear the message area to avoid next transaction reading - * sensitive results from previous transaction */ - memset(sep->shared_addr, 0, - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - - /* - * Check that the size of the mapped range is as the size of the message - * shared area - */ - if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) { - error = -EINVAL; - goto end_function_with_error; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] shared_addr is %p\n", - current->pid, sep->shared_addr); - - /* Get bus address */ - bus_addr = sep->shared_bus; - - if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - dev_dbg(&sep->pdev->dev, "[PID%d] remap_pfn_range failed\n", - current->pid); - error = -EAGAIN; - goto end_function_with_error; - } - - /* Update call status */ - set_bit(SEP_LEGACY_MMAP_DONE_OFFSET, &call_status->status); - - goto end_function; - -end_function_with_error: - /* Clear our transaction */ - sep_end_transaction_handler(sep, NULL, call_status, - my_queue_elem); - -end_function: - return error; -} - -/** - * sep_poll - poll handler - * @filp: pointer to struct file - * @wait: pointer to poll_table - * - * Called by the OS when the kernel is asked to do a poll on - * a SEP file handle. - */ -static unsigned int sep_poll(struct file *filp, poll_table *wait) -{ - struct sep_private_data * const private_data = filp->private_data; - struct sep_call_status *call_status = &private_data->call_status; - struct sep_device *sep = private_data->device; - u32 mask = 0; - u32 retval = 0; - u32 retval2 = 0; - unsigned long lock_irq_flag; - - /* Am I the process that owns the transaction? */ - if (sep_check_transaction_owner(sep)) { - dev_dbg(&sep->pdev->dev, "[PID%d] poll pid not owner\n", - current->pid); - mask = POLLERR; - goto end_function; - } - - /* Check if send command or send_reply were activated previously */ - if (0 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &call_status->status)) { - dev_warn(&sep->pdev->dev, "[PID%d] sendmsg not called\n", - current->pid); - mask = POLLERR; - goto end_function; - } - - /* Add the event to the polling wait table */ - dev_dbg(&sep->pdev->dev, "[PID%d] poll: calling wait sep_event\n", - current->pid); - - poll_wait(filp, &sep->event_interrupt, wait); - - dev_dbg(&sep->pdev->dev, - "[PID%d] poll: send_ct is %lx reply ct is %lx\n", - current->pid, sep->send_ct, sep->reply_ct); - - /* Check if error occurred during poll */ - retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); - if ((retval2 != 0x0) && (retval2 != 0x8)) { - dev_dbg(&sep->pdev->dev, "[PID%d] poll; poll error %x\n", - current->pid, retval2); - mask |= POLLERR; - goto end_function; - } - - spin_lock_irqsave(&sep->snd_rply_lck, lock_irq_flag); - - if (sep->send_ct == sep->reply_ct) { - spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); - retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - dev_dbg(&sep->pdev->dev, - "[PID%d] poll: data ready check (GPR2) %x\n", - current->pid, retval); - - /* Check if printf request */ - if ((retval >> 30) & 0x1) { - dev_dbg(&sep->pdev->dev, - "[PID%d] poll: SEP printf request\n", - current->pid); - goto end_function; - } - - /* Check if the this is SEP reply or request */ - if (retval >> 31) { - dev_dbg(&sep->pdev->dev, - "[PID%d] poll: SEP request\n", - current->pid); - } else { - dev_dbg(&sep->pdev->dev, - "[PID%d] poll: normal return\n", - current->pid); - sep_dump_message(sep); - dev_dbg(&sep->pdev->dev, - "[PID%d] poll; SEP reply POLLIN|POLLRDNORM\n", - current->pid); - mask |= POLLIN | POLLRDNORM; - } - set_bit(SEP_LEGACY_POLL_DONE_OFFSET, &call_status->status); - } else { - spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); - dev_dbg(&sep->pdev->dev, - "[PID%d] poll; no reply; returning mask of 0\n", - current->pid); - mask = 0; - } - -end_function: - return mask; -} - -/** - * sep_time_address - address in SEP memory of time - * @sep: SEP device we want the address from - * - * Return the address of the two dwords in memory used for time - * setting. - */ -static u32 *sep_time_address(struct sep_device *sep) -{ - return sep->shared_addr + - SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES; -} - -/** - * sep_set_time - set the SEP time - * @sep: the SEP we are setting the time for - * - * Calculates time and sets it at the predefined address. - * Called with the SEP mutex held. - */ -static unsigned long sep_set_time(struct sep_device *sep) -{ - struct timeval time; - u32 *time_addr; /* Address of time as seen by the kernel */ - - do_gettimeofday(&time); - - /* Set value in the SYSTEM MEMORY offset */ - time_addr = sep_time_address(sep); - - time_addr[0] = SEP_TIME_VAL_TOKEN; - time_addr[1] = time.tv_sec; - - dev_dbg(&sep->pdev->dev, "[PID%d] time.tv_sec is %lu\n", - current->pid, time.tv_sec); - dev_dbg(&sep->pdev->dev, "[PID%d] time_addr is %p\n", - current->pid, time_addr); - dev_dbg(&sep->pdev->dev, "[PID%d] sep->shared_addr is %p\n", - current->pid, sep->shared_addr); - - return time.tv_sec; -} - -/** - * sep_send_command_handler - kick off a command - * @sep: SEP being signalled - * - * This function raises interrupt to SEP that signals that is has a new - * command from the host - * - * Note that this function does fall under the ioctl lock - */ -int sep_send_command_handler(struct sep_device *sep) -{ - unsigned long lock_irq_flag; - u32 *msg_pool; - int error = 0; - - /* Basic sanity check; set msg pool to start of shared area */ - msg_pool = (u32 *)sep->shared_addr; - msg_pool += 2; - - /* Look for start msg token */ - if (*msg_pool != SEP_START_MSG_TOKEN) { - dev_warn(&sep->pdev->dev, "start message token not present\n"); - error = -EPROTO; - goto end_function; - } - - /* Do we have a reasonable size? */ - msg_pool += 1; - if ((*msg_pool < 2) || - (*msg_pool > SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES)) { - dev_warn(&sep->pdev->dev, "invalid message size\n"); - error = -EPROTO; - goto end_function; - } - - /* Does the command look reasonable? */ - msg_pool += 1; - if (*msg_pool < 2) { - dev_warn(&sep->pdev->dev, "invalid message opcode\n"); - error = -EPROTO; - goto end_function; - } - -#if defined(CONFIG_PM_RUNTIME) && defined(SEP_ENABLE_RUNTIME_PM) - dev_dbg(&sep->pdev->dev, "[PID%d] before pm sync status 0x%X\n", - current->pid, - sep->pdev->dev.power.runtime_status); - sep->in_use = 1; /* device is about to be used */ - pm_runtime_get_sync(&sep->pdev->dev); -#endif - - if (test_and_set_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags)) { - error = -EPROTO; - goto end_function; - } - sep->in_use = 1; /* device is about to be used */ - sep_set_time(sep); - - sep_dump_message(sep); - - /* Update counter */ - spin_lock_irqsave(&sep->snd_rply_lck, lock_irq_flag); - sep->send_ct++; - spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); - - dev_dbg(&sep->pdev->dev, - "[PID%d] sep_send_command_handler send_ct %lx reply_ct %lx\n", - current->pid, sep->send_ct, sep->reply_ct); - - /* Send interrupt to SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); - -end_function: - return error; -} - -/** - * sep_crypto_dma - - * @sep: pointer to struct sep_device - * @sg: pointer to struct scatterlist - * @direction: - * @dma_maps: pointer to place a pointer to array of dma maps - * This is filled in; anything previous there will be lost - * The structure for dma maps is sep_dma_map - * @returns number of dma maps on success; negative on error - * - * This creates the dma table from the scatterlist - * It is used only for kernel crypto as it works with scatterlists - * representation of data buffers - * - */ -static int sep_crypto_dma( - struct sep_device *sep, - struct scatterlist *sg, - struct sep_dma_map **dma_maps, - enum dma_data_direction direction) -{ - struct scatterlist *temp_sg; - - u32 count_segment; - u32 count_mapped; - struct sep_dma_map *sep_dma; - int ct1; - - if (sg->length == 0) - return 0; - - /* Count the segments */ - temp_sg = sg; - count_segment = 0; - while (temp_sg) { - count_segment += 1; - temp_sg = scatterwalk_sg_next(temp_sg); - } - dev_dbg(&sep->pdev->dev, - "There are (hex) %x segments in sg\n", count_segment); - - /* DMA map segments */ - count_mapped = dma_map_sg(&sep->pdev->dev, sg, - count_segment, direction); - - dev_dbg(&sep->pdev->dev, - "There are (hex) %x maps in sg\n", count_mapped); - - if (count_mapped == 0) { - dev_dbg(&sep->pdev->dev, "Cannot dma_map_sg\n"); - return -ENOMEM; - } - - sep_dma = kmalloc(sizeof(struct sep_dma_map) * - count_mapped, GFP_ATOMIC); - - if (sep_dma == NULL) { - dev_dbg(&sep->pdev->dev, "Cannot allocate dma_maps\n"); - return -ENOMEM; - } - - for_each_sg(sg, temp_sg, count_mapped, ct1) { - sep_dma[ct1].dma_addr = sg_dma_address(temp_sg); - sep_dma[ct1].size = sg_dma_len(temp_sg); - dev_dbg(&sep->pdev->dev, "(all hex) map %x dma %lx len %lx\n", - ct1, (unsigned long)sep_dma[ct1].dma_addr, - (unsigned long)sep_dma[ct1].size); - } - - *dma_maps = sep_dma; - return count_mapped; -} - -/** - * sep_crypto_lli - - * @sep: pointer to struct sep_device - * @sg: pointer to struct scatterlist - * @data_size: total data size - * @direction: - * @dma_maps: pointer to place a pointer to array of dma maps - * This is filled in; anything previous there will be lost - * The structure for dma maps is sep_dma_map - * @lli_maps: pointer to place a pointer to array of lli maps - * This is filled in; anything previous there will be lost - * The structure for dma maps is sep_dma_map - * @returns number of dma maps on success; negative on error - * - * This creates the LLI table from the scatterlist - * It is only used for kernel crypto as it works exclusively - * with scatterlists (struct scatterlist) representation of - * data buffers - */ -static int sep_crypto_lli( - struct sep_device *sep, - struct scatterlist *sg, - struct sep_dma_map **maps, - struct sep_lli_entry **llis, - u32 data_size, - enum dma_data_direction direction) -{ - int ct1; - struct sep_lli_entry *sep_lli; - struct sep_dma_map *sep_map; - - int nbr_ents; - - nbr_ents = sep_crypto_dma(sep, sg, maps, direction); - if (nbr_ents <= 0) { - dev_dbg(&sep->pdev->dev, "crypto_dma failed %x\n", - nbr_ents); - return nbr_ents; - } - - sep_map = *maps; - - sep_lli = kmalloc(sizeof(struct sep_lli_entry) * nbr_ents, GFP_ATOMIC); - - if (sep_lli == NULL) { - dev_dbg(&sep->pdev->dev, "Cannot allocate lli_maps\n"); - - kfree(*maps); - *maps = NULL; - return -ENOMEM; - } - - for (ct1 = 0; ct1 < nbr_ents; ct1 += 1) { - sep_lli[ct1].bus_address = (u32)sep_map[ct1].dma_addr; - - /* Maximum for page is total data size */ - if (sep_map[ct1].size > data_size) - sep_map[ct1].size = data_size; - - sep_lli[ct1].block_size = (u32)sep_map[ct1].size; - } - - *llis = sep_lli; - return nbr_ents; -} - -/** - * sep_lock_kernel_pages - map kernel pages for DMA - * @sep: pointer to struct sep_device - * @kernel_virt_addr: address of data buffer in kernel - * @data_size: size of data - * @lli_array_ptr: lli array - * @in_out_flag: input into device or output from device - * - * This function locks all the physical pages of the kernel virtual buffer - * and construct a basic lli array, where each entry holds the physical - * page address and the size that application data holds in this page - * This function is used only during kernel crypto mod calls from within - * the kernel (when ioctl is not used) - * - * This is used only for kernel crypto. Kernel pages - * are handled differently as they are done via - * scatter gather lists (struct scatterlist) - */ -static int sep_lock_kernel_pages(struct sep_device *sep, - unsigned long kernel_virt_addr, - u32 data_size, - struct sep_lli_entry **lli_array_ptr, - int in_out_flag, - struct sep_dma_context *dma_ctx) - -{ - u32 num_pages; - struct scatterlist *sg; - - /* Array of lli */ - struct sep_lli_entry *lli_array; - /* Map array */ - struct sep_dma_map *map_array; - - enum dma_data_direction direction; - - lli_array = NULL; - map_array = NULL; - - if (in_out_flag == SEP_DRIVER_IN_FLAG) { - direction = DMA_TO_DEVICE; - sg = dma_ctx->src_sg; - } else { - direction = DMA_FROM_DEVICE; - sg = dma_ctx->dst_sg; - } - - num_pages = sep_crypto_lli(sep, sg, &map_array, &lli_array, - data_size, direction); - - if (num_pages <= 0) { - dev_dbg(&sep->pdev->dev, "sep_crypto_lli returned error %x\n", - num_pages); - return -ENOMEM; - } - - /* Put mapped kernel sg into kernel resource array */ - - /* Set output params according to the in_out flag */ - if (in_out_flag == SEP_DRIVER_IN_FLAG) { - *lli_array_ptr = lli_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages = - num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = - NULL; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = - map_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_num_entries = - num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].src_sg = - dma_ctx->src_sg; - } else { - *lli_array_ptr = lli_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages = - num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = - NULL; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = - map_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. - out_map_num_entries = num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].dst_sg = - dma_ctx->dst_sg; - } - - return 0; -} - -/** - * sep_lock_user_pages - lock and map user pages for DMA - * @sep: pointer to struct sep_device - * @app_virt_addr: user memory data buffer - * @data_size: size of data buffer - * @lli_array_ptr: lli array - * @in_out_flag: input or output to device - * - * This function locks all the physical pages of the application - * virtual buffer and construct a basic lli array, where each entry - * holds the physical page address and the size that application - * data holds in this physical pages - */ -static int sep_lock_user_pages(struct sep_device *sep, - u32 app_virt_addr, - u32 data_size, - struct sep_lli_entry **lli_array_ptr, - int in_out_flag, - struct sep_dma_context *dma_ctx) - -{ - int error = 0; - u32 count; - int result; - /* The the page of the end address of the user space buffer */ - u32 end_page; - /* The page of the start address of the user space buffer */ - u32 start_page; - /* The range in pages */ - u32 num_pages; - /* Array of pointers to page */ - struct page **page_array; - /* Array of lli */ - struct sep_lli_entry *lli_array; - /* Map array */ - struct sep_dma_map *map_array; - - /* Set start and end pages and num pages */ - end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = app_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; - - dev_dbg(&sep->pdev->dev, - "[PID%d] lock user pages app_virt_addr is %x\n", - current->pid, app_virt_addr); - - dev_dbg(&sep->pdev->dev, "[PID%d] data_size is (hex) %x\n", - current->pid, data_size); - dev_dbg(&sep->pdev->dev, "[PID%d] start_page is (hex) %x\n", - current->pid, start_page); - dev_dbg(&sep->pdev->dev, "[PID%d] end_page is (hex) %x\n", - current->pid, end_page); - dev_dbg(&sep->pdev->dev, "[PID%d] num_pages is (hex) %x\n", - current->pid, num_pages); - - /* Allocate array of pages structure pointers */ - page_array = kmalloc_array(num_pages, sizeof(struct page *), - GFP_ATOMIC); - if (!page_array) { - error = -ENOMEM; - goto end_function; - } - - map_array = kmalloc_array(num_pages, sizeof(struct sep_dma_map), - GFP_ATOMIC); - if (!map_array) { - error = -ENOMEM; - goto end_function_with_error1; - } - - lli_array = kmalloc_array(num_pages, sizeof(struct sep_lli_entry), - GFP_ATOMIC); - if (!lli_array) { - error = -ENOMEM; - goto end_function_with_error2; - } - - /* Convert the application virtual address into a set of physical */ - result = get_user_pages_fast(app_virt_addr, num_pages, - ((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1), page_array); - - /* Check the number of pages locked - if not all then exit with error */ - if (result != num_pages) { - dev_warn(&sep->pdev->dev, - "[PID%d] not all pages locked by get_user_pages, result 0x%X, num_pages 0x%X\n", - current->pid, result, num_pages); - error = -ENOMEM; - goto end_function_with_error3; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] get_user_pages succeeded\n", - current->pid); - - /* - * Fill the array using page array data and - * map the pages - this action will also flush the cache as needed - */ - for (count = 0; count < num_pages; count++) { - /* Fill the map array */ - map_array[count].dma_addr = - dma_map_page(&sep->pdev->dev, page_array[count], - 0, PAGE_SIZE, DMA_BIDIRECTIONAL); - - map_array[count].size = PAGE_SIZE; - - /* Fill the lli array entry */ - lli_array[count].bus_address = (u32)map_array[count].dma_addr; - lli_array[count].block_size = PAGE_SIZE; - - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n", - current->pid, count, - (unsigned long)lli_array[count].bus_address, - count, lli_array[count].block_size); - } - - /* Check the offset for the first page */ - lli_array[0].bus_address = - lli_array[0].bus_address + (app_virt_addr & (~PAGE_MASK)); - - /* Check that not all the data is in the first page only */ - if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; - else - lli_array[0].block_size = - PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); - - dev_dbg(&sep->pdev->dev, - "[PID%d] After check if page 0 has all data\n", - current->pid); - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n", - current->pid, - (unsigned long)lli_array[0].bus_address, - lli_array[0].block_size); - - /* Check the size of the last page */ - if (num_pages > 1) { - lli_array[num_pages - 1].block_size = - (app_virt_addr + data_size) & (~PAGE_MASK); - if (lli_array[num_pages - 1].block_size == 0) - lli_array[num_pages - 1].block_size = PAGE_SIZE; - - dev_dbg(&sep->pdev->dev, - "[PID%d] After last page size adjustment\n", - current->pid); - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n", - current->pid, - num_pages - 1, - (unsigned long)lli_array[num_pages - 1].bus_address, - num_pages - 1, - lli_array[num_pages - 1].block_size); - } - - /* Set output params according to the in_out flag */ - if (in_out_flag == SEP_DRIVER_IN_FLAG) { - *lli_array_ptr = lli_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages = - num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = - page_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = - map_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_num_entries = - num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].src_sg = NULL; - } else { - *lli_array_ptr = lli_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages = - num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = - page_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = - map_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. - out_map_num_entries = num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].dst_sg = NULL; - } - goto end_function; - -end_function_with_error3: - /* Free lli array */ - kfree(lli_array); - -end_function_with_error2: - kfree(map_array); - -end_function_with_error1: - /* Free page array */ - kfree(page_array); - -end_function: - return error; -} - -/** - * sep_lli_table_secure_dma - get lli array for IMR addresses - * @sep: pointer to struct sep_device - * @app_virt_addr: user memory data buffer - * @data_size: size of data buffer - * @lli_array_ptr: lli array - * @in_out_flag: not used - * @dma_ctx: pointer to struct sep_dma_context - * - * This function creates lli tables for outputting data to - * IMR memory, which is memory that cannot be accessed by the - * the x86 processor. - */ -static int sep_lli_table_secure_dma(struct sep_device *sep, - u32 app_virt_addr, - u32 data_size, - struct sep_lli_entry **lli_array_ptr, - int in_out_flag, - struct sep_dma_context *dma_ctx) - -{ - u32 count; - /* The the page of the end address of the user space buffer */ - u32 end_page; - /* The page of the start address of the user space buffer */ - u32 start_page; - /* The range in pages */ - u32 num_pages; - /* Array of lli */ - struct sep_lli_entry *lli_array; - - /* Set start and end pages and num pages */ - end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = app_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; - - dev_dbg(&sep->pdev->dev, - "[PID%d] lock user pages app_virt_addr is %x\n", - current->pid, app_virt_addr); - - dev_dbg(&sep->pdev->dev, "[PID%d] data_size is (hex) %x\n", - current->pid, data_size); - dev_dbg(&sep->pdev->dev, "[PID%d] start_page is (hex) %x\n", - current->pid, start_page); - dev_dbg(&sep->pdev->dev, "[PID%d] end_page is (hex) %x\n", - current->pid, end_page); - dev_dbg(&sep->pdev->dev, "[PID%d] num_pages is (hex) %x\n", - current->pid, num_pages); - - lli_array = kmalloc_array(num_pages, sizeof(struct sep_lli_entry), - GFP_ATOMIC); - if (!lli_array) - return -ENOMEM; - - /* - * Fill the lli_array - */ - start_page = start_page << PAGE_SHIFT; - for (count = 0; count < num_pages; count++) { - /* Fill the lli array entry */ - lli_array[count].bus_address = start_page; - lli_array[count].block_size = PAGE_SIZE; - - start_page += PAGE_SIZE; - - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n", - current->pid, - count, (unsigned long)lli_array[count].bus_address, - count, lli_array[count].block_size); - } - - /* Check the offset for the first page */ - lli_array[0].bus_address = - lli_array[0].bus_address + (app_virt_addr & (~PAGE_MASK)); - - /* Check that not all the data is in the first page only */ - if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; - else - lli_array[0].block_size = - PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); - - dev_dbg(&sep->pdev->dev, - "[PID%d] After check if page 0 has all data\n" - "lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n", - current->pid, - (unsigned long)lli_array[0].bus_address, - lli_array[0].block_size); - - /* Check the size of the last page */ - if (num_pages > 1) { - lli_array[num_pages - 1].block_size = - (app_virt_addr + data_size) & (~PAGE_MASK); - if (lli_array[num_pages - 1].block_size == 0) - lli_array[num_pages - 1].block_size = PAGE_SIZE; - - dev_dbg(&sep->pdev->dev, - "[PID%d] After last page size adjustment\n" - "lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n", - current->pid, num_pages - 1, - (unsigned long)lli_array[num_pages - 1].bus_address, - num_pages - 1, - lli_array[num_pages - 1].block_size); - } - *lli_array_ptr = lli_array; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages = num_pages; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = NULL; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_num_entries = 0; - - return 0; -} - -/** - * sep_calculate_lli_table_max_size - size the LLI table - * @sep: pointer to struct sep_device - * @lli_in_array_ptr - * @num_array_entries - * @last_table_flag - * - * This function calculates the size of data that can be inserted into - * the lli table from this array, such that either the table is full - * (all entries are entered), or there are no more entries in the - * lli array - */ -static u32 sep_calculate_lli_table_max_size(struct sep_device *sep, - struct sep_lli_entry *lli_in_array_ptr, - u32 num_array_entries, - u32 *last_table_flag) -{ - u32 counter; - /* Table data size */ - u32 table_data_size = 0; - /* Data size for the next table */ - u32 next_table_data_size; - - *last_table_flag = 0; - - /* - * Calculate the data in the out lli table till we fill the whole - * table or till the data has ended - */ - for (counter = 0; - (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && - (counter < num_array_entries); counter++) - table_data_size += lli_in_array_ptr[counter].block_size; - - /* - * Check if we reached the last entry, - * meaning this ia the last table to build, - * and no need to check the block alignment - */ - if (counter == num_array_entries) { - /* Set the last table flag */ - *last_table_flag = 1; - goto end_function; - } - - /* - * Calculate the data size of the next table. - * Stop if no entries left or if data size is more the DMA restriction - */ - next_table_data_size = 0; - for (; counter < num_array_entries; counter++) { - next_table_data_size += lli_in_array_ptr[counter].block_size; - if (next_table_data_size >= SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) - break; - } - - /* - * Check if the next table data size is less then DMA rstriction. - * if it is - recalculate the current table size, so that the next - * table data size will be adaquete for DMA - */ - if (next_table_data_size && - next_table_data_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) - - table_data_size -= (SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE - - next_table_data_size); - -end_function: - return table_data_size; -} - -/** - * sep_build_lli_table - build an lli array for the given table - * @sep: pointer to struct sep_device - * @lli_array_ptr: pointer to lli array - * @lli_table_ptr: pointer to lli table - * @num_processed_entries_ptr: pointer to number of entries - * @num_table_entries_ptr: pointer to number of tables - * @table_data_size: total data size - * - * Builds an lli table from the lli_array according to - * the given size of data - */ -static void sep_build_lli_table(struct sep_device *sep, - struct sep_lli_entry *lli_array_ptr, - struct sep_lli_entry *lli_table_ptr, - u32 *num_processed_entries_ptr, - u32 *num_table_entries_ptr, - u32 table_data_size) -{ - /* Current table data size */ - u32 curr_table_data_size; - /* Counter of lli array entry */ - u32 array_counter; - - /* Init current table data size and lli array entry counter */ - curr_table_data_size = 0; - array_counter = 0; - *num_table_entries_ptr = 1; - - dev_dbg(&sep->pdev->dev, - "[PID%d] build lli table table_data_size: (hex) %x\n", - current->pid, table_data_size); - - /* Fill the table till table size reaches the needed amount */ - while (curr_table_data_size < table_data_size) { - /* Update the number of entries in table */ - (*num_table_entries_ptr)++; - - lli_table_ptr->bus_address = - cpu_to_le32(lli_array_ptr[array_counter].bus_address); - - lli_table_ptr->block_size = - cpu_to_le32(lli_array_ptr[array_counter].block_size); - - curr_table_data_size += lli_array_ptr[array_counter].block_size; - - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_table_ptr is %p\n", - current->pid, lli_table_ptr); - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_table_ptr->bus_address: %08lx\n", - current->pid, - (unsigned long)lli_table_ptr->bus_address); - - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_table_ptr->block_size is (hex) %x\n", - current->pid, lli_table_ptr->block_size); - - /* Check for overflow of the table data */ - if (curr_table_data_size > table_data_size) { - dev_dbg(&sep->pdev->dev, - "[PID%d] curr_table_data_size too large\n", - current->pid); - - /* Update the size of block in the table */ - lli_table_ptr->block_size = - cpu_to_le32(lli_table_ptr->block_size) - - (curr_table_data_size - table_data_size); - - /* Update the physical address in the lli array */ - lli_array_ptr[array_counter].bus_address += - cpu_to_le32(lli_table_ptr->block_size); - - /* Update the block size left in the lli array */ - lli_array_ptr[array_counter].block_size = - (curr_table_data_size - table_data_size); - } else - /* Advance to the next entry in the lli_array */ - array_counter++; - - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_table_ptr->bus_address is %08lx\n", - current->pid, - (unsigned long)lli_table_ptr->bus_address); - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_table_ptr->block_size is (hex) %x\n", - current->pid, - lli_table_ptr->block_size); - - /* Move to the next entry in table */ - lli_table_ptr++; - } - - /* Set the info entry to default */ - lli_table_ptr->bus_address = 0xffffffff; - lli_table_ptr->block_size = 0; - - /* Set the output parameter */ - *num_processed_entries_ptr += array_counter; -} - -/** - * sep_shared_area_virt_to_bus - map shared area to bus address - * @sep: pointer to struct sep_device - * @virt_address: virtual address to convert - * - * This functions returns the physical address inside shared area according - * to the virtual address. It can be either on the external RAM device - * (ioremapped), or on the system RAM - * This implementation is for the external RAM - */ -static dma_addr_t sep_shared_area_virt_to_bus(struct sep_device *sep, - void *virt_address) -{ - dev_dbg(&sep->pdev->dev, "[PID%d] sh virt to phys v %p\n", - current->pid, virt_address); - dev_dbg(&sep->pdev->dev, "[PID%d] sh virt to phys p %08lx\n", - current->pid, - (unsigned long) - sep->shared_bus + (virt_address - sep->shared_addr)); - - return sep->shared_bus + (size_t)(virt_address - sep->shared_addr); -} - -/** - * sep_shared_area_bus_to_virt - map shared area bus address to kernel - * @sep: pointer to struct sep_device - * @bus_address: bus address to convert - * - * This functions returns the virtual address inside shared area - * according to the physical address. It can be either on the - * external RAM device (ioremapped), or on the system RAM - * This implementation is for the external RAM - */ -static void *sep_shared_area_bus_to_virt(struct sep_device *sep, - dma_addr_t bus_address) -{ - dev_dbg(&sep->pdev->dev, "[PID%d] shared bus to virt b=%lx v=%lx\n", - current->pid, - (unsigned long)bus_address, (unsigned long)(sep->shared_addr + - (size_t)(bus_address - sep->shared_bus))); - - return sep->shared_addr + (size_t)(bus_address - sep->shared_bus); -} - -/** - * sep_debug_print_lli_tables - dump LLI table - * @sep: pointer to struct sep_device - * @lli_table_ptr: pointer to sep_lli_entry - * @num_table_entries: number of entries - * @table_data_size: total data size - * - * Walk the the list of the print created tables and print all the data - */ -static void sep_debug_print_lli_tables(struct sep_device *sep, - struct sep_lli_entry *lli_table_ptr, - unsigned long num_table_entries, - unsigned long table_data_size) -{ -#ifdef DEBUG - unsigned long table_count = 1; - unsigned long entries_count = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_debug_print_lli_tables start\n", - current->pid); - if (num_table_entries == 0) { - dev_dbg(&sep->pdev->dev, "[PID%d] no table to print\n", - current->pid); - return; - } - - while ((unsigned long)lli_table_ptr->bus_address != 0xffffffff) { - dev_dbg(&sep->pdev->dev, - "[PID%d] lli table %08lx, table_data_size is (hex) %lx\n", - current->pid, table_count, table_data_size); - dev_dbg(&sep->pdev->dev, - "[PID%d] num_table_entries is (hex) %lx\n", - current->pid, num_table_entries); - - /* Print entries of the table (without info entry) */ - for (entries_count = 0; entries_count < num_table_entries; - entries_count++, lli_table_ptr++) { - dev_dbg(&sep->pdev->dev, - "[PID%d] lli_table_ptr address is %08lx\n", - current->pid, - (unsigned long)lli_table_ptr); - - dev_dbg(&sep->pdev->dev, - "[PID%d] phys address is %08lx block size is (hex) %x\n", - current->pid, - (unsigned long)lli_table_ptr->bus_address, - lli_table_ptr->block_size); - } - - /* Point to the info entry */ - lli_table_ptr--; - - dev_dbg(&sep->pdev->dev, - "[PID%d] phys lli_table_ptr->block_size is (hex) %x\n", - current->pid, - lli_table_ptr->block_size); - - dev_dbg(&sep->pdev->dev, - "[PID%d] phys lli_table_ptr->physical_address is %08lx\n", - current->pid, - (unsigned long)lli_table_ptr->bus_address); - - table_data_size = lli_table_ptr->block_size & 0xffffff; - num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff; - - dev_dbg(&sep->pdev->dev, - "[PID%d] phys table_data_size is (hex) %lx num_table_entries is %lx bus_address is%lx\n", - current->pid, - table_data_size, - num_table_entries, - (unsigned long)lli_table_ptr->bus_address); - - if ((unsigned long)lli_table_ptr->bus_address != 0xffffffff) - lli_table_ptr = (struct sep_lli_entry *) - sep_shared_bus_to_virt(sep, - (unsigned long)lli_table_ptr->bus_address); - - table_count++; - } - dev_dbg(&sep->pdev->dev, "[PID%d] sep_debug_print_lli_tables end\n", - current->pid); -#endif -} - -/** - * sep_prepare_empty_lli_table - create a blank LLI table - * @sep: pointer to struct sep_device - * @lli_table_addr_ptr: pointer to lli table - * @num_entries_ptr: pointer to number of entries - * @table_data_size_ptr: point to table data size - * @dmatables_region: Optional buffer for DMA tables - * @dma_ctx: DMA context - * - * This function creates empty lli tables when there is no data - */ -static void sep_prepare_empty_lli_table(struct sep_device *sep, - dma_addr_t *lli_table_addr_ptr, - u32 *num_entries_ptr, - u32 *table_data_size_ptr, - void **dmatables_region, - struct sep_dma_context *dma_ctx) -{ - struct sep_lli_entry *lli_table_ptr; - - /* Find the area for new table */ - lli_table_ptr = - (struct sep_lli_entry *)(sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - dma_ctx->num_lli_tables_created * sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - if (dmatables_region && *dmatables_region) - lli_table_ptr = *dmatables_region; - - lli_table_ptr->bus_address = 0; - lli_table_ptr->block_size = 0; - - lli_table_ptr++; - lli_table_ptr->bus_address = 0xFFFFFFFF; - lli_table_ptr->block_size = 0; - - /* Set the output parameter value */ - *lli_table_addr_ptr = sep->shared_bus + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - dma_ctx->num_lli_tables_created * - sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* Set the num of entries and table data size for empty table */ - *num_entries_ptr = 2; - *table_data_size_ptr = 0; - - /* Update the number of created tables */ - dma_ctx->num_lli_tables_created++; -} - -/** - * sep_prepare_input_dma_table - prepare input DMA mappings - * @sep: pointer to struct sep_device - * @data_size: - * @block_size: - * @lli_table_ptr: - * @num_entries_ptr: - * @table_data_size_ptr: - * @is_kva: set for kernel data (kernel crypt io call) - * - * This function prepares only input DMA table for synchronic symmetric - * operations (HASH) - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_prepare_input_dma_table(struct sep_device *sep, - unsigned long app_virt_addr, - u32 data_size, - u32 block_size, - dma_addr_t *lli_table_ptr, - u32 *num_entries_ptr, - u32 *table_data_size_ptr, - bool is_kva, - void **dmatables_region, - struct sep_dma_context *dma_ctx -) -{ - int error = 0; - /* Pointer to the info entry of the table - the last entry */ - struct sep_lli_entry *info_entry_ptr; - /* Array of pointers to page */ - struct sep_lli_entry *lli_array_ptr; - /* Points to the first entry to be processed in the lli_in_array */ - u32 current_entry = 0; - /* Num entries in the virtual buffer */ - u32 sep_lli_entries = 0; - /* Lli table pointer */ - struct sep_lli_entry *in_lli_table_ptr; - /* The total data in one table */ - u32 table_data_size = 0; - /* Flag for last table */ - u32 last_table_flag = 0; - /* Number of entries in lli table */ - u32 num_entries_in_table = 0; - /* Next table address */ - void *lli_table_alloc_addr = NULL; - void *dma_lli_table_alloc_addr = NULL; - void *dma_in_lli_table_ptr = NULL; - - dev_dbg(&sep->pdev->dev, - "[PID%d] prepare intput dma tbl data size: (hex) %x\n", - current->pid, data_size); - - dev_dbg(&sep->pdev->dev, "[PID%d] block_size is (hex) %x\n", - current->pid, block_size); - - /* Initialize the pages pointers */ - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages = 0; - - /* Set the kernel address for first table to be allocated */ - lli_table_alloc_addr = (void *)(sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - dma_ctx->num_lli_tables_created * sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - if (data_size == 0) { - if (dmatables_region) { - error = sep_allocate_dmatables_region(sep, - dmatables_region, - dma_ctx, - 1); - if (error) - return error; - } - /* Special case - create meptu table - 2 entries, zero data */ - sep_prepare_empty_lli_table(sep, lli_table_ptr, - num_entries_ptr, table_data_size_ptr, - dmatables_region, dma_ctx); - goto update_dcb_counter; - } - - /* Check if the pages are in Kernel Virtual Address layout */ - if (is_kva) - error = sep_lock_kernel_pages(sep, app_virt_addr, - data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG, - dma_ctx); - else - /* - * Lock the pages of the user buffer - * and translate them to pages - */ - error = sep_lock_user_pages(sep, app_virt_addr, - data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG, - dma_ctx); - - if (error) - goto end_function; - - dev_dbg(&sep->pdev->dev, - "[PID%d] output sep_in_num_pages is (hex) %x\n", - current->pid, - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages); - - current_entry = 0; - info_entry_ptr = NULL; - - sep_lli_entries = - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages; - - dma_lli_table_alloc_addr = lli_table_alloc_addr; - if (dmatables_region) { - error = sep_allocate_dmatables_region(sep, - dmatables_region, - dma_ctx, - sep_lli_entries); - if (error) - goto end_function_error; - lli_table_alloc_addr = *dmatables_region; - } - - /* Loop till all the entries in in array are processed */ - while (current_entry < sep_lli_entries) { - /* Set the new input and output tables */ - in_lli_table_ptr = - (struct sep_lli_entry *)lli_table_alloc_addr; - dma_in_lli_table_ptr = - (struct sep_lli_entry *)dma_lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - dma_lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - if (dma_lli_table_alloc_addr > - ((void *)sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) { - error = -ENOMEM; - goto end_function_error; - } - - /* Update the number of created tables */ - dma_ctx->num_lli_tables_created++; - - /* Calculate the maximum size of data for input table */ - table_data_size = sep_calculate_lli_table_max_size(sep, - &lli_array_ptr[current_entry], - (sep_lli_entries - current_entry), - &last_table_flag); - - /* - * If this is not the last table - - * then align it to the block size - */ - if (!last_table_flag) - table_data_size = - (table_data_size / block_size) * block_size; - - dev_dbg(&sep->pdev->dev, - "[PID%d] output table_data_size is (hex) %x\n", - current->pid, - table_data_size); - - /* Construct input lli table */ - sep_build_lli_table(sep, &lli_array_ptr[current_entry], - in_lli_table_ptr, - ¤t_entry, &num_entries_in_table, table_data_size); - - if (info_entry_ptr == NULL) { - /* Set the output parameters to physical addresses */ - *lli_table_ptr = sep_shared_area_virt_to_bus(sep, - dma_in_lli_table_ptr); - *num_entries_ptr = num_entries_in_table; - *table_data_size_ptr = table_data_size; - - dev_dbg(&sep->pdev->dev, - "[PID%d] output lli_table_in_ptr is %08lx\n", - current->pid, - (unsigned long)*lli_table_ptr); - - } else { - /* Update the info entry of the previous in table */ - info_entry_ptr->bus_address = - sep_shared_area_virt_to_bus(sep, - dma_in_lli_table_ptr); - info_entry_ptr->block_size = - ((num_entries_in_table) << 24) | - (table_data_size); - } - /* Save the pointer to the info entry of the current tables */ - info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1; - } - /* Print input tables */ - if (!dmatables_region) { - sep_debug_print_lli_tables(sep, (struct sep_lli_entry *) - sep_shared_area_bus_to_virt(sep, *lli_table_ptr), - *num_entries_ptr, *table_data_size_ptr); - } - - /* The array of the pages */ - kfree(lli_array_ptr); - -update_dcb_counter: - /* Update DCB counter */ - dma_ctx->nr_dcb_creat++; - goto end_function; - -end_function_error: - /* Free all the allocated resources */ - kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array); - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = NULL; - kfree(lli_array_ptr); - kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array); - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; - -end_function: - return error; -} - -/** - * sep_construct_dma_tables_from_lli - prepare AES/DES mappings - * @sep: pointer to struct sep_device - * @lli_in_array: - * @sep_in_lli_entries: - * @lli_out_array: - * @sep_out_lli_entries - * @block_size - * @lli_table_in_ptr - * @lli_table_out_ptr - * @in_num_entries_ptr - * @out_num_entries_ptr - * @table_data_size_ptr - * - * This function creates the input and output DMA tables for - * symmetric operations (AES/DES) according to the block - * size from LLI arays - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_construct_dma_tables_from_lli( - struct sep_device *sep, - struct sep_lli_entry *lli_in_array, - u32 sep_in_lli_entries, - struct sep_lli_entry *lli_out_array, - u32 sep_out_lli_entries, - u32 block_size, - dma_addr_t *lli_table_in_ptr, - dma_addr_t *lli_table_out_ptr, - u32 *in_num_entries_ptr, - u32 *out_num_entries_ptr, - u32 *table_data_size_ptr, - void **dmatables_region, - struct sep_dma_context *dma_ctx) -{ - /* Points to the area where next lli table can be allocated */ - void *lli_table_alloc_addr = NULL; - /* - * Points to the area in shared region where next lli table - * can be allocated - */ - void *dma_lli_table_alloc_addr = NULL; - /* Input lli table in dmatables_region or shared region */ - struct sep_lli_entry *in_lli_table_ptr = NULL; - /* Input lli table location in the shared region */ - struct sep_lli_entry *dma_in_lli_table_ptr = NULL; - /* Output lli table in dmatables_region or shared region */ - struct sep_lli_entry *out_lli_table_ptr = NULL; - /* Output lli table location in the shared region */ - struct sep_lli_entry *dma_out_lli_table_ptr = NULL; - /* Pointer to the info entry of the table - the last entry */ - struct sep_lli_entry *info_in_entry_ptr = NULL; - /* Pointer to the info entry of the table - the last entry */ - struct sep_lli_entry *info_out_entry_ptr = NULL; - /* Points to the first entry to be processed in the lli_in_array */ - u32 current_in_entry = 0; - /* Points to the first entry to be processed in the lli_out_array */ - u32 current_out_entry = 0; - /* Max size of the input table */ - u32 in_table_data_size = 0; - /* Max size of the output table */ - u32 out_table_data_size = 0; - /* Flag te signifies if this is the last tables build */ - u32 last_table_flag = 0; - /* The data size that should be in table */ - u32 table_data_size = 0; - /* Number of entries in the input table */ - u32 num_entries_in_table = 0; - /* Number of entries in the output table */ - u32 num_entries_out_table = 0; - - if (!dma_ctx) { - dev_warn(&sep->pdev->dev, "DMA context uninitialized\n"); - return -EINVAL; - } - - /* Initiate to point after the message area */ - lli_table_alloc_addr = (void *)(sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - (dma_ctx->num_lli_tables_created * - (sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP))); - dma_lli_table_alloc_addr = lli_table_alloc_addr; - - if (dmatables_region) { - /* 2 for both in+out table */ - if (sep_allocate_dmatables_region(sep, - dmatables_region, - dma_ctx, - 2*sep_in_lli_entries)) - return -ENOMEM; - lli_table_alloc_addr = *dmatables_region; - } - - /* Loop till all the entries in in array are not processed */ - while (current_in_entry < sep_in_lli_entries) { - /* Set the new input and output tables */ - in_lli_table_ptr = - (struct sep_lli_entry *)lli_table_alloc_addr; - dma_in_lli_table_ptr = - (struct sep_lli_entry *)dma_lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - dma_lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* Set the first output tables */ - out_lli_table_ptr = - (struct sep_lli_entry *)lli_table_alloc_addr; - dma_out_lli_table_ptr = - (struct sep_lli_entry *)dma_lli_table_alloc_addr; - - /* Check if the DMA table area limit was overrun */ - if ((dma_lli_table_alloc_addr + sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP) > - ((void *)sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) { - dev_warn(&sep->pdev->dev, "dma table limit overrun\n"); - return -ENOMEM; - } - - /* Update the number of the lli tables created */ - dma_ctx->num_lli_tables_created += 2; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - dma_lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* Calculate the maximum size of data for input table */ - in_table_data_size = - sep_calculate_lli_table_max_size(sep, - &lli_in_array[current_in_entry], - (sep_in_lli_entries - current_in_entry), - &last_table_flag); - - /* Calculate the maximum size of data for output table */ - out_table_data_size = - sep_calculate_lli_table_max_size(sep, - &lli_out_array[current_out_entry], - (sep_out_lli_entries - current_out_entry), - &last_table_flag); - - if (!last_table_flag) { - in_table_data_size = (in_table_data_size / - block_size) * block_size; - out_table_data_size = (out_table_data_size / - block_size) * block_size; - } - - table_data_size = in_table_data_size; - if (table_data_size > out_table_data_size) - table_data_size = out_table_data_size; - - dev_dbg(&sep->pdev->dev, - "[PID%d] construct tables from lli in_table_data_size is (hex) %x\n", - current->pid, in_table_data_size); - - dev_dbg(&sep->pdev->dev, - "[PID%d] construct tables from lli out_table_data_size is (hex) %x\n", - current->pid, out_table_data_size); - - /* Construct input lli table */ - sep_build_lli_table(sep, &lli_in_array[current_in_entry], - in_lli_table_ptr, - ¤t_in_entry, - &num_entries_in_table, - table_data_size); - - /* Construct output lli table */ - sep_build_lli_table(sep, &lli_out_array[current_out_entry], - out_lli_table_ptr, - ¤t_out_entry, - &num_entries_out_table, - table_data_size); - - /* If info entry is null - this is the first table built */ - if (info_in_entry_ptr == NULL || info_out_entry_ptr == NULL) { - /* Set the output parameters to physical addresses */ - *lli_table_in_ptr = - sep_shared_area_virt_to_bus(sep, dma_in_lli_table_ptr); - - *in_num_entries_ptr = num_entries_in_table; - - *lli_table_out_ptr = - sep_shared_area_virt_to_bus(sep, - dma_out_lli_table_ptr); - - *out_num_entries_ptr = num_entries_out_table; - *table_data_size_ptr = table_data_size; - - dev_dbg(&sep->pdev->dev, - "[PID%d] output lli_table_in_ptr is %08lx\n", - current->pid, - (unsigned long)*lli_table_in_ptr); - dev_dbg(&sep->pdev->dev, - "[PID%d] output lli_table_out_ptr is %08lx\n", - current->pid, - (unsigned long)*lli_table_out_ptr); - } else { - /* Update the info entry of the previous in table */ - info_in_entry_ptr->bus_address = - sep_shared_area_virt_to_bus(sep, - dma_in_lli_table_ptr); - - info_in_entry_ptr->block_size = - ((num_entries_in_table) << 24) | - (table_data_size); - - /* Update the info entry of the previous in table */ - info_out_entry_ptr->bus_address = - sep_shared_area_virt_to_bus(sep, - dma_out_lli_table_ptr); - - info_out_entry_ptr->block_size = - ((num_entries_out_table) << 24) | - (table_data_size); - - dev_dbg(&sep->pdev->dev, - "[PID%d] output lli_table_in_ptr:%08lx %08x\n", - current->pid, - (unsigned long)info_in_entry_ptr->bus_address, - info_in_entry_ptr->block_size); - - dev_dbg(&sep->pdev->dev, - "[PID%d] output lli_table_out_ptr: %08lx %08x\n", - current->pid, - (unsigned long)info_out_entry_ptr->bus_address, - info_out_entry_ptr->block_size); - } - - /* Save the pointer to the info entry of the current tables */ - info_in_entry_ptr = in_lli_table_ptr + - num_entries_in_table - 1; - info_out_entry_ptr = out_lli_table_ptr + - num_entries_out_table - 1; - - dev_dbg(&sep->pdev->dev, - "[PID%d] output num_entries_out_table is %x\n", - current->pid, - (u32)num_entries_out_table); - dev_dbg(&sep->pdev->dev, - "[PID%d] output info_in_entry_ptr is %lx\n", - current->pid, - (unsigned long)info_in_entry_ptr); - dev_dbg(&sep->pdev->dev, - "[PID%d] output info_out_entry_ptr is %lx\n", - current->pid, - (unsigned long)info_out_entry_ptr); - } - - /* Print input tables */ - if (!dmatables_region) { - sep_debug_print_lli_tables( - sep, - (struct sep_lli_entry *) - sep_shared_area_bus_to_virt(sep, *lli_table_in_ptr), - *in_num_entries_ptr, - *table_data_size_ptr); - } - - /* Print output tables */ - if (!dmatables_region) { - sep_debug_print_lli_tables( - sep, - (struct sep_lli_entry *) - sep_shared_area_bus_to_virt(sep, *lli_table_out_ptr), - *out_num_entries_ptr, - *table_data_size_ptr); - } - - return 0; -} - -/** - * sep_prepare_input_output_dma_table - prepare DMA I/O table - * @app_virt_in_addr: - * @app_virt_out_addr: - * @data_size: - * @block_size: - * @lli_table_in_ptr: - * @lli_table_out_ptr: - * @in_num_entries_ptr: - * @out_num_entries_ptr: - * @table_data_size_ptr: - * @is_kva: set for kernel data; used only for kernel crypto module - * - * This function builds input and output DMA tables for synchronic - * symmetric operations (AES, DES, HASH). It also checks that each table - * is of the modular block size - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_prepare_input_output_dma_table(struct sep_device *sep, - unsigned long app_virt_in_addr, - unsigned long app_virt_out_addr, - u32 data_size, - u32 block_size, - dma_addr_t *lli_table_in_ptr, - dma_addr_t *lli_table_out_ptr, - u32 *in_num_entries_ptr, - u32 *out_num_entries_ptr, - u32 *table_data_size_ptr, - bool is_kva, - void **dmatables_region, - struct sep_dma_context *dma_ctx) - -{ - int error = 0; - /* Array of pointers of page */ - struct sep_lli_entry *lli_in_array; - /* Array of pointers of page */ - struct sep_lli_entry *lli_out_array; - - if (!dma_ctx) { - error = -EINVAL; - goto end_function; - } - - if (data_size == 0) { - /* Prepare empty table for input and output */ - if (dmatables_region) { - error = sep_allocate_dmatables_region( - sep, - dmatables_region, - dma_ctx, - 2); - if (error) - goto end_function; - } - sep_prepare_empty_lli_table(sep, lli_table_in_ptr, - in_num_entries_ptr, table_data_size_ptr, - dmatables_region, dma_ctx); - - sep_prepare_empty_lli_table(sep, lli_table_out_ptr, - out_num_entries_ptr, table_data_size_ptr, - dmatables_region, dma_ctx); - - goto update_dcb_counter; - } - - /* Initialize the pages pointers */ - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL; - - /* Lock the pages of the buffer and translate them to pages */ - if (is_kva) { - dev_dbg(&sep->pdev->dev, "[PID%d] Locking kernel input pages\n", - current->pid); - error = sep_lock_kernel_pages(sep, app_virt_in_addr, - data_size, &lli_in_array, SEP_DRIVER_IN_FLAG, - dma_ctx); - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] sep_lock_kernel_pages for input virtual buffer failed\n", - current->pid); - - goto end_function; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] Locking kernel output pages\n", - current->pid); - error = sep_lock_kernel_pages(sep, app_virt_out_addr, - data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG, - dma_ctx); - - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] sep_lock_kernel_pages for output virtual buffer failed\n", - current->pid); - - goto end_function_free_lli_in; - } - } else { - dev_dbg(&sep->pdev->dev, "[PID%d] Locking user input pages\n", - current->pid); - error = sep_lock_user_pages(sep, app_virt_in_addr, - data_size, &lli_in_array, SEP_DRIVER_IN_FLAG, - dma_ctx); - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] sep_lock_user_pages for input virtual buffer failed\n", - current->pid); - - goto end_function; - } - - if (dma_ctx->secure_dma) { - /* secure_dma requires use of non accessible memory */ - dev_dbg(&sep->pdev->dev, "[PID%d] in secure_dma\n", - current->pid); - error = sep_lli_table_secure_dma(sep, - app_virt_out_addr, data_size, &lli_out_array, - SEP_DRIVER_OUT_FLAG, dma_ctx); - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] secure dma table setup for output virtual buffer failed\n", - current->pid); - - goto end_function_free_lli_in; - } - } else { - /* For normal, non-secure dma */ - dev_dbg(&sep->pdev->dev, "[PID%d] not in secure_dma\n", - current->pid); - - dev_dbg(&sep->pdev->dev, - "[PID%d] Locking user output pages\n", - current->pid); - - error = sep_lock_user_pages(sep, app_virt_out_addr, - data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG, - dma_ctx); - - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] sep_lock_user_pages for output virtual buffer failed\n", - current->pid); - - goto end_function_free_lli_in; - } - } - } - - dev_dbg(&sep->pdev->dev, - "[PID%d] After lock; prep input output dma table sep_in_num_pages is (hex) %x\n", - current->pid, - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages); - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_out_num_pages is (hex) %x\n", - current->pid, - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages); - - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is (hex) %x\n", - current->pid, SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - /* Call the function that creates table from the lli arrays */ - dev_dbg(&sep->pdev->dev, "[PID%d] calling create table from lli\n", - current->pid); - error = sep_construct_dma_tables_from_lli( - sep, lli_in_array, - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. - in_num_pages, - lli_out_array, - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. - out_num_pages, - block_size, lli_table_in_ptr, lli_table_out_ptr, - in_num_entries_ptr, out_num_entries_ptr, - table_data_size_ptr, dmatables_region, dma_ctx); - - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] sep_construct_dma_tables_from_lli failed\n", - current->pid); - goto end_function_with_error; - } - - kfree(lli_out_array); - kfree(lli_in_array); - -update_dcb_counter: - /* Update DCB counter */ - dma_ctx->nr_dcb_creat++; - - goto end_function; - -end_function_with_error: - kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array); - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = NULL; - kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array); - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL; - kfree(lli_out_array); - -end_function_free_lli_in: - kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array); - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = NULL; - kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array); - dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; - kfree(lli_in_array); - -end_function: - return error; -} - -/** - * sep_prepare_input_output_dma_table_in_dcb - prepare control blocks - * @app_in_address: unsigned long; for data buffer in (user space) - * @app_out_address: unsigned long; for data buffer out (user space) - * @data_in_size: u32; for size of data - * @block_size: u32; for block size - * @tail_block_size: u32; for size of tail block - * @isapplet: bool; to indicate external app - * @is_kva: bool; kernel buffer; only used for kernel crypto module - * @secure_dma; indicates whether this is secure_dma using IMR - * - * This function prepares the linked DMA tables and puts the - * address for the linked list of tables inta a DCB (data control - * block) the address of which is known by the SEP hardware - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, - unsigned long app_in_address, - unsigned long app_out_address, - u32 data_in_size, - u32 block_size, - u32 tail_block_size, - bool isapplet, - bool is_kva, - bool secure_dma, - struct sep_dcblock *dcb_region, - void **dmatables_region, - struct sep_dma_context **dma_ctx, - struct scatterlist *src_sg, - struct scatterlist *dst_sg) -{ - int error = 0; - /* Size of tail */ - u32 tail_size = 0; - /* Address of the created DCB table */ - struct sep_dcblock *dcb_table_ptr = NULL; - /* The physical address of the first input DMA table */ - dma_addr_t in_first_mlli_address = 0; - /* Number of entries in the first input DMA table */ - u32 in_first_num_entries = 0; - /* The physical address of the first output DMA table */ - dma_addr_t out_first_mlli_address = 0; - /* Number of entries in the first output DMA table */ - u32 out_first_num_entries = 0; - /* Data in the first input/output table */ - u32 first_data_size = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] app_in_address %lx\n", - current->pid, app_in_address); - - dev_dbg(&sep->pdev->dev, "[PID%d] app_out_address %lx\n", - current->pid, app_out_address); - - dev_dbg(&sep->pdev->dev, "[PID%d] data_in_size %x\n", - current->pid, data_in_size); - - dev_dbg(&sep->pdev->dev, "[PID%d] block_size %x\n", - current->pid, block_size); - - dev_dbg(&sep->pdev->dev, "[PID%d] tail_block_size %x\n", - current->pid, tail_block_size); - - dev_dbg(&sep->pdev->dev, "[PID%d] isapplet %x\n", - current->pid, isapplet); - - dev_dbg(&sep->pdev->dev, "[PID%d] is_kva %x\n", - current->pid, is_kva); - - dev_dbg(&sep->pdev->dev, "[PID%d] src_sg %p\n", - current->pid, src_sg); - - dev_dbg(&sep->pdev->dev, "[PID%d] dst_sg %p\n", - current->pid, dst_sg); - - if (!dma_ctx) { - dev_warn(&sep->pdev->dev, "[PID%d] no DMA context pointer\n", - current->pid); - error = -EINVAL; - goto end_function; - } - - if (*dma_ctx) { - /* In case there are multiple DCBs for this transaction */ - dev_dbg(&sep->pdev->dev, "[PID%d] DMA context already set\n", - current->pid); - } else { - *dma_ctx = kzalloc(sizeof(**dma_ctx), GFP_KERNEL); - if (!(*dma_ctx)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] Not enough memory for DMA context\n", - current->pid); - error = -ENOMEM; - goto end_function; - } - dev_dbg(&sep->pdev->dev, - "[PID%d] Created DMA context addr at 0x%p\n", - current->pid, *dma_ctx); - } - - (*dma_ctx)->secure_dma = secure_dma; - - /* these are for kernel crypto only */ - (*dma_ctx)->src_sg = src_sg; - (*dma_ctx)->dst_sg = dst_sg; - - if ((*dma_ctx)->nr_dcb_creat == SEP_MAX_NUM_SYNC_DMA_OPS) { - /* No more DCBs to allocate */ - dev_dbg(&sep->pdev->dev, "[PID%d] no more DCBs available\n", - current->pid); - error = -ENOSPC; - goto end_function_error; - } - - /* Allocate new DCB */ - if (dcb_region) { - dcb_table_ptr = dcb_region; - } else { - dcb_table_ptr = (struct sep_dcblock *)(sep->shared_addr + - SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES + - ((*dma_ctx)->nr_dcb_creat * - sizeof(struct sep_dcblock))); - } - - /* Set the default values in the DCB */ - dcb_table_ptr->input_mlli_address = 0; - dcb_table_ptr->input_mlli_num_entries = 0; - dcb_table_ptr->input_mlli_data_size = 0; - dcb_table_ptr->output_mlli_address = 0; - dcb_table_ptr->output_mlli_num_entries = 0; - dcb_table_ptr->output_mlli_data_size = 0; - dcb_table_ptr->tail_data_size = 0; - dcb_table_ptr->out_vr_tail_pt = 0; - - if (isapplet) { - /* Check if there is enough data for DMA operation */ - if (data_in_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) { - if (is_kva) { - error = -ENODEV; - goto end_function_error; - } else { - if (copy_from_user(dcb_table_ptr->tail_data, - (void __user *)app_in_address, - data_in_size)) { - error = -EFAULT; - goto end_function_error; - } - } - - dcb_table_ptr->tail_data_size = data_in_size; - - /* Set the output user-space address for mem2mem op */ - if (app_out_address) - dcb_table_ptr->out_vr_tail_pt = - (aligned_u64)app_out_address; - - /* - * Update both data length parameters in order to avoid - * second data copy and allow building of empty mlli - * tables - */ - tail_size = 0x0; - data_in_size = 0x0; - - } else { - if (!app_out_address) { - tail_size = data_in_size % block_size; - if (!tail_size) { - if (tail_block_size == block_size) - tail_size = block_size; - } - } else { - tail_size = 0; - } - } - if (tail_size) { - if (tail_size > sizeof(dcb_table_ptr->tail_data)) - return -EINVAL; - if (is_kva) { - error = -ENODEV; - goto end_function_error; - } else { - /* We have tail data - copy it to DCB */ - if (copy_from_user(dcb_table_ptr->tail_data, - (void __user *)(app_in_address + - data_in_size - tail_size), tail_size)) { - error = -EFAULT; - goto end_function_error; - } - } - if (app_out_address) - /* - * Calculate the output address - * according to tail data size - */ - dcb_table_ptr->out_vr_tail_pt = - (aligned_u64)app_out_address + - data_in_size - tail_size; - - /* Save the real tail data size */ - dcb_table_ptr->tail_data_size = tail_size; - /* - * Update the data size without the tail - * data size AKA data for the dma - */ - data_in_size = (data_in_size - tail_size); - } - } - /* Check if we need to build only input table or input/output */ - if (app_out_address) { - /* Prepare input/output tables */ - error = sep_prepare_input_output_dma_table(sep, - app_in_address, - app_out_address, - data_in_size, - block_size, - &in_first_mlli_address, - &out_first_mlli_address, - &in_first_num_entries, - &out_first_num_entries, - &first_data_size, - is_kva, - dmatables_region, - *dma_ctx); - } else { - /* Prepare input tables */ - error = sep_prepare_input_dma_table(sep, - app_in_address, - data_in_size, - block_size, - &in_first_mlli_address, - &in_first_num_entries, - &first_data_size, - is_kva, - dmatables_region, - *dma_ctx); - } - - if (error) { - dev_warn(&sep->pdev->dev, - "prepare DMA table call failed from prepare DCB call\n"); - goto end_function_error; - } - - /* Set the DCB values */ - dcb_table_ptr->input_mlli_address = in_first_mlli_address; - dcb_table_ptr->input_mlli_num_entries = in_first_num_entries; - dcb_table_ptr->input_mlli_data_size = first_data_size; - dcb_table_ptr->output_mlli_address = out_first_mlli_address; - dcb_table_ptr->output_mlli_num_entries = out_first_num_entries; - dcb_table_ptr->output_mlli_data_size = first_data_size; - - goto end_function; - -end_function_error: - kfree(*dma_ctx); - *dma_ctx = NULL; - -end_function: - return error; -} - -/** - * sep_free_dma_tables_and_dcb - free DMA tables and DCBs - * @sep: pointer to struct sep_device - * @isapplet: indicates external application (used for kernel access) - * @is_kva: indicates kernel addresses (only used for kernel crypto) - * - * This function frees the DMA tables and DCB - */ -static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet, - bool is_kva, struct sep_dma_context **dma_ctx) -{ - struct sep_dcblock *dcb_table_ptr; - unsigned long pt_hold; - void *tail_pt; - - int i = 0; - int error = 0; - int error_temp = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_free_dma_tables_and_dcb\n", - current->pid); - if (!dma_ctx || !*dma_ctx) /* nothing to be done here*/ - return 0; - - if (!(*dma_ctx)->secure_dma && isapplet) { - dev_dbg(&sep->pdev->dev, "[PID%d] handling applet\n", - current->pid); - - /* Tail stuff is only for non secure_dma */ - /* Set pointer to first DCB table */ - dcb_table_ptr = (struct sep_dcblock *) - (sep->shared_addr + - SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES); - - /** - * Go over each DCB and see if - * tail pointer must be updated - */ - for (i = 0; i < (*dma_ctx)->nr_dcb_creat; - i++, dcb_table_ptr++) { - if (dcb_table_ptr->out_vr_tail_pt) { - pt_hold = (unsigned long)dcb_table_ptr-> - out_vr_tail_pt; - tail_pt = (void *)pt_hold; - if (is_kva) { - error = -ENODEV; - break; - } - error_temp = copy_to_user( - (void __user *)tail_pt, - dcb_table_ptr->tail_data, - dcb_table_ptr->tail_data_size); - if (error_temp) { - /* Release the DMA resource */ - error = -EFAULT; - break; - } - } - } - } - - /* Free the output pages, if any */ - sep_free_dma_table_data_handler(sep, dma_ctx); - - dev_dbg(&sep->pdev->dev, "[PID%d] sep_free_dma_tables_and_dcb end\n", - current->pid); - - return error; -} - -/** - * sep_prepare_dcb_handler - prepare a control block - * @sep: pointer to struct sep_device - * @arg: pointer to user parameters - * @secure_dma: indicate whether we are using secure_dma on IMR - * - * This function will retrieve the RAR buffer physical addresses, type - * & size corresponding to the RAR handles provided in the buffers vector. - */ -static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg, - bool secure_dma, - struct sep_dma_context **dma_ctx) -{ - int error; - /* Command arguments */ - static struct build_dcb_struct command_args; - - /* Get the command arguments */ - if (copy_from_user(&command_args, (void __user *)arg, - sizeof(struct build_dcb_struct))) { - error = -EFAULT; - goto end_function; - } - - dev_dbg(&sep->pdev->dev, - "[PID%d] prep dcb handler app_in_address is %08llx\n", - current->pid, command_args.app_in_address); - dev_dbg(&sep->pdev->dev, - "[PID%d] app_out_address is %08llx\n", - current->pid, command_args.app_out_address); - dev_dbg(&sep->pdev->dev, - "[PID%d] data_size is %x\n", - current->pid, command_args.data_in_size); - dev_dbg(&sep->pdev->dev, - "[PID%d] block_size is %x\n", - current->pid, command_args.block_size); - dev_dbg(&sep->pdev->dev, - "[PID%d] tail block_size is %x\n", - current->pid, command_args.tail_block_size); - dev_dbg(&sep->pdev->dev, - "[PID%d] is_applet is %x\n", - current->pid, command_args.is_applet); - - if (!command_args.app_in_address) { - dev_warn(&sep->pdev->dev, - "[PID%d] null app_in_address\n", current->pid); - error = -EINVAL; - goto end_function; - } - - error = sep_prepare_input_output_dma_table_in_dcb(sep, - (unsigned long)command_args.app_in_address, - (unsigned long)command_args.app_out_address, - command_args.data_in_size, command_args.block_size, - command_args.tail_block_size, - command_args.is_applet, false, - secure_dma, NULL, NULL, dma_ctx, NULL, NULL); - -end_function: - return error; -} - -/** - * sep_free_dcb_handler - free control block resources - * @sep: pointer to struct sep_device - * - * This function frees the DCB resources and updates the needed - * user-space buffers. - */ -static int sep_free_dcb_handler(struct sep_device *sep, - struct sep_dma_context **dma_ctx) -{ - if (!dma_ctx || !(*dma_ctx)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] no dma context defined, nothing to free\n", - current->pid); - return -EINVAL; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] free dcbs num of DCBs %x\n", - current->pid, - (*dma_ctx)->nr_dcb_creat); - - return sep_free_dma_tables_and_dcb(sep, false, false, dma_ctx); -} - -/** - * sep_ioctl - ioctl handler for sep device - * @filp: pointer to struct file - * @cmd: command - * @arg: pointer to argument structure - * - * Implement the ioctl methods available on the SEP device. - */ -static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct sep_private_data * const private_data = filp->private_data; - struct sep_call_status *call_status = &private_data->call_status; - struct sep_device *sep = private_data->device; - struct sep_dma_context **dma_ctx = &private_data->dma_ctx; - struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; - int error = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] ioctl cmd 0x%x\n", - current->pid, cmd); - dev_dbg(&sep->pdev->dev, "[PID%d] dma context addr 0x%p\n", - current->pid, *dma_ctx); - - /* Make sure we own this device */ - error = sep_check_transaction_owner(sep); - if (error) { - dev_dbg(&sep->pdev->dev, "[PID%d] ioctl pid is not owner\n", - current->pid); - goto end_function; - } - - /* Check that sep_mmap has been called before */ - if (0 == test_bit(SEP_LEGACY_MMAP_DONE_OFFSET, - &call_status->status)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] mmap not called\n", current->pid); - error = -EPROTO; - goto end_function; - } - - /* Check that the command is for SEP device */ - if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) { - error = -ENOTTY; - goto end_function; - } - - switch (cmd) { - case SEP_IOCSENDSEPCOMMAND: - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCSENDSEPCOMMAND start\n", - current->pid); - if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &call_status->status)) { - dev_warn(&sep->pdev->dev, - "[PID%d] send msg already done\n", - current->pid); - error = -EPROTO; - goto end_function; - } - /* Send command to SEP */ - error = sep_send_command_handler(sep); - if (!error) - set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &call_status->status); - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCSENDSEPCOMMAND end\n", - current->pid); - break; - case SEP_IOCENDTRANSACTION: - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCENDTRANSACTION start\n", - current->pid); - error = sep_end_transaction_handler(sep, dma_ctx, call_status, - my_queue_elem); - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCENDTRANSACTION end\n", - current->pid); - break; - case SEP_IOCPREPAREDCB: - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCPREPAREDCB start\n", - current->pid); - /* fall-through */ - case SEP_IOCPREPAREDCB_SECURE_DMA: - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCPREPAREDCB_SECURE_DMA start\n", - current->pid); - if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &call_status->status)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] dcb prep needed before send msg\n", - current->pid); - error = -EPROTO; - goto end_function; - } - - if (!arg) { - dev_dbg(&sep->pdev->dev, - "[PID%d] dcb null arg\n", current->pid); - error = -EINVAL; - goto end_function; - } - - if (cmd == SEP_IOCPREPAREDCB) { - /* No secure dma */ - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCPREPAREDCB (no secure_dma)\n", - current->pid); - - error = sep_prepare_dcb_handler(sep, arg, false, - dma_ctx); - } else { - /* Secure dma */ - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOC_POC (with secure_dma)\n", - current->pid); - - error = sep_prepare_dcb_handler(sep, arg, true, - dma_ctx); - } - dev_dbg(&sep->pdev->dev, "[PID%d] dcb's end\n", - current->pid); - break; - case SEP_IOCFREEDCB: - dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCFREEDCB start\n", - current->pid); - case SEP_IOCFREEDCB_SECURE_DMA: - dev_dbg(&sep->pdev->dev, - "[PID%d] SEP_IOCFREEDCB_SECURE_DMA start\n", - current->pid); - error = sep_free_dcb_handler(sep, dma_ctx); - dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCFREEDCB end\n", - current->pid); - break; - default: - error = -ENOTTY; - dev_dbg(&sep->pdev->dev, "[PID%d] default end\n", - current->pid); - break; - } - -end_function: - dev_dbg(&sep->pdev->dev, "[PID%d] ioctl end\n", current->pid); - - return error; -} - -/** - * sep_inthandler - interrupt handler for sep device - * @irq: interrupt - * @dev_id: device id - */ -static irqreturn_t sep_inthandler(int irq, void *dev_id) -{ - unsigned long lock_irq_flag; - u32 reg_val, reg_val2 = 0; - struct sep_device *sep = dev_id; - irqreturn_t int_error = IRQ_HANDLED; - - /* Are we in power save? */ -#if defined(CONFIG_PM_RUNTIME) && defined(SEP_ENABLE_RUNTIME_PM) - if (sep->pdev->dev.power.runtime_status != RPM_ACTIVE) { - dev_dbg(&sep->pdev->dev, "interrupt during pwr save\n"); - return IRQ_NONE; - } -#endif - - if (test_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags) == 0) { - dev_dbg(&sep->pdev->dev, "interrupt while nobody using sep\n"); - return IRQ_NONE; - } - - /* Read the IRR register to check if this is SEP interrupt */ - reg_val = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR); - - dev_dbg(&sep->pdev->dev, "sep int: IRR REG val: %x\n", reg_val); - - if (reg_val & (0x1 << 13)) { - /* Lock and update the counter of reply messages */ - spin_lock_irqsave(&sep->snd_rply_lck, lock_irq_flag); - sep->reply_ct++; - spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); - - dev_dbg(&sep->pdev->dev, "sep int: send_ct %lx reply_ct %lx\n", - sep->send_ct, sep->reply_ct); - - /* Is this a kernel client request */ - if (sep->in_kernel) { - tasklet_schedule(&sep->finish_tasklet); - goto finished_interrupt; - } - - /* Is this printf or daemon request? */ - reg_val2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - dev_dbg(&sep->pdev->dev, - "SEP Interrupt - GPR2 is %08x\n", reg_val2); - - clear_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags); - - if ((reg_val2 >> 30) & 0x1) { - dev_dbg(&sep->pdev->dev, "int: printf request\n"); - } else if (reg_val2 >> 31) { - dev_dbg(&sep->pdev->dev, "int: daemon request\n"); - } else { - dev_dbg(&sep->pdev->dev, "int: SEP reply\n"); - wake_up(&sep->event_interrupt); - } - } else { - dev_dbg(&sep->pdev->dev, "int: not SEP interrupt\n"); - int_error = IRQ_NONE; - } - -finished_interrupt: - - if (int_error == IRQ_HANDLED) - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, reg_val); - - return int_error; -} - -/** - * sep_reconfig_shared_area - reconfigure shared area - * @sep: pointer to struct sep_device - * - * Reconfig the shared area between HOST and SEP - needed in case - * the DX_CC_Init function was called before OS loading. - */ -static int sep_reconfig_shared_area(struct sep_device *sep) -{ - int ret_val; - - /* use to limit waiting for SEP */ - unsigned long end_time; - - /* Send the new SHARED MESSAGE AREA to the SEP */ - dev_dbg(&sep->pdev->dev, "reconfig shared; sending %08llx to sep\n", - (unsigned long long)sep->shared_bus); - - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus); - - /* Poll for SEP response */ - ret_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); - - end_time = jiffies + (WAIT_TIME * HZ); - - while ((time_before(jiffies, end_time)) && (ret_val != 0xffffffff) && - (ret_val != sep->shared_bus)) - ret_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); - - /* Check the return value (register) */ - if (ret_val != sep->shared_bus) { - dev_warn(&sep->pdev->dev, "could not reconfig shared area\n"); - dev_warn(&sep->pdev->dev, "result was %x\n", ret_val); - ret_val = -ENOMEM; - } else { - ret_val = 0; - } - - dev_dbg(&sep->pdev->dev, "reconfig shared area end\n"); - - return ret_val; -} - -/** - * sep_activate_dcb_dmatables_context - Takes DCB & DMA tables - * contexts into use - * @sep: SEP device - * @dcb_region: DCB region copy - * @dmatables_region: MLLI/DMA tables copy - * @dma_ctx: DMA context for current transaction - */ -ssize_t sep_activate_dcb_dmatables_context(struct sep_device *sep, - struct sep_dcblock **dcb_region, - void **dmatables_region, - struct sep_dma_context *dma_ctx) -{ - void *dmaregion_free_start = NULL; - void *dmaregion_free_end = NULL; - void *dcbregion_free_start = NULL; - void *dcbregion_free_end = NULL; - ssize_t error = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] activating dcb/dma region\n", - current->pid); - - if (1 > dma_ctx->nr_dcb_creat) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid number of dcbs to activate 0x%08X\n", - current->pid, dma_ctx->nr_dcb_creat); - error = -EINVAL; - goto end_function; - } - - dmaregion_free_start = sep->shared_addr - + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES; - dmaregion_free_end = dmaregion_free_start - + SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES - 1; - - if (dmaregion_free_start - + dma_ctx->dmatables_len > dmaregion_free_end) { - error = -ENOMEM; - goto end_function; - } - memcpy(dmaregion_free_start, - *dmatables_region, - dma_ctx->dmatables_len); - /* Free MLLI table copy */ - kfree(*dmatables_region); - *dmatables_region = NULL; - - /* Copy thread's DCB table copy to DCB table region */ - dcbregion_free_start = sep->shared_addr + - SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES; - dcbregion_free_end = dcbregion_free_start + - (SEP_MAX_NUM_SYNC_DMA_OPS * - sizeof(struct sep_dcblock)) - 1; - - if (dcbregion_free_start - + (dma_ctx->nr_dcb_creat * sizeof(struct sep_dcblock)) - > dcbregion_free_end) { - error = -ENOMEM; - goto end_function; - } - - memcpy(dcbregion_free_start, - *dcb_region, - dma_ctx->nr_dcb_creat * sizeof(struct sep_dcblock)); - - /* Print the tables */ - dev_dbg(&sep->pdev->dev, "activate: input table\n"); - sep_debug_print_lli_tables(sep, - (struct sep_lli_entry *)sep_shared_area_bus_to_virt(sep, - (*dcb_region)->input_mlli_address), - (*dcb_region)->input_mlli_num_entries, - (*dcb_region)->input_mlli_data_size); - - dev_dbg(&sep->pdev->dev, "activate: output table\n"); - sep_debug_print_lli_tables(sep, - (struct sep_lli_entry *)sep_shared_area_bus_to_virt(sep, - (*dcb_region)->output_mlli_address), - (*dcb_region)->output_mlli_num_entries, - (*dcb_region)->output_mlli_data_size); - - dev_dbg(&sep->pdev->dev, - "[PID%d] printing activated tables\n", current->pid); - -end_function: - kfree(*dmatables_region); - *dmatables_region = NULL; - - kfree(*dcb_region); - *dcb_region = NULL; - - return error; -} - -/** - * sep_create_dcb_dmatables_context - Creates DCB & MLLI/DMA table context - * @sep: SEP device - * @dcb_region: DCB region buf to create for current transaction - * @dmatables_region: MLLI/DMA tables buf to create for current transaction - * @dma_ctx: DMA context buf to create for current transaction - * @user_dcb_args: User arguments for DCB/MLLI creation - * @num_dcbs: Number of DCBs to create - * @secure_dma: Indicate use of IMR restricted memory secure dma - */ -static ssize_t sep_create_dcb_dmatables_context(struct sep_device *sep, - struct sep_dcblock **dcb_region, - void **dmatables_region, - struct sep_dma_context **dma_ctx, - const struct build_dcb_struct __user *user_dcb_args, - const u32 num_dcbs, bool secure_dma) -{ - int error = 0; - int i = 0; - struct build_dcb_struct *dcb_args = NULL; - - dev_dbg(&sep->pdev->dev, "[PID%d] creating dcb/dma region\n", - current->pid); - - if (!dcb_region || !dma_ctx || !dmatables_region || !user_dcb_args) { - error = -EINVAL; - goto end_function; - } - - if (SEP_MAX_NUM_SYNC_DMA_OPS < num_dcbs) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid number of dcbs 0x%08X\n", - current->pid, num_dcbs); - error = -EINVAL; - goto end_function; - } - - dcb_args = kcalloc(num_dcbs, sizeof(struct build_dcb_struct), - GFP_KERNEL); - if (!dcb_args) { - error = -ENOMEM; - goto end_function; - } - - if (copy_from_user(dcb_args, - user_dcb_args, - num_dcbs * sizeof(struct build_dcb_struct))) { - error = -EFAULT; - goto end_function; - } - - /* Allocate thread-specific memory for DCB */ - *dcb_region = kzalloc(num_dcbs * sizeof(struct sep_dcblock), - GFP_KERNEL); - if (!(*dcb_region)) { - error = -ENOMEM; - goto end_function; - } - - /* Prepare DCB and MLLI table into the allocated regions */ - for (i = 0; i < num_dcbs; i++) { - error = sep_prepare_input_output_dma_table_in_dcb(sep, - (unsigned long)dcb_args[i].app_in_address, - (unsigned long)dcb_args[i].app_out_address, - dcb_args[i].data_in_size, - dcb_args[i].block_size, - dcb_args[i].tail_block_size, - dcb_args[i].is_applet, - false, secure_dma, - *dcb_region, dmatables_region, - dma_ctx, - NULL, - NULL); - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] dma table creation failed\n", - current->pid); - goto end_function; - } - - if (dcb_args[i].app_in_address != 0) - (*dma_ctx)->input_data_len += dcb_args[i].data_in_size; - } - -end_function: - kfree(dcb_args); - return error; -} - -/** - * sep_create_dcb_dmatables_context_kernel - Creates DCB & MLLI/DMA table context - * for kernel crypto - * @sep: SEP device - * @dcb_region: DCB region buf to create for current transaction - * @dmatables_region: MLLI/DMA tables buf to create for current transaction - * @dma_ctx: DMA context buf to create for current transaction - * @user_dcb_args: User arguments for DCB/MLLI creation - * @num_dcbs: Number of DCBs to create - * This does that same thing as sep_create_dcb_dmatables_context - * except that it is used only for the kernel crypto operation. It is - * separate because there is no user data involved; the dcb data structure - * is specific for kernel crypto (build_dcb_struct_kernel) - */ -int sep_create_dcb_dmatables_context_kernel(struct sep_device *sep, - struct sep_dcblock **dcb_region, - void **dmatables_region, - struct sep_dma_context **dma_ctx, - const struct build_dcb_struct_kernel *dcb_data, - const u32 num_dcbs) -{ - int error = 0; - int i = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] creating dcb/dma region\n", - current->pid); - - if (!dcb_region || !dma_ctx || !dmatables_region || !dcb_data) { - error = -EINVAL; - goto end_function; - } - - if (SEP_MAX_NUM_SYNC_DMA_OPS < num_dcbs) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid number of dcbs 0x%08X\n", - current->pid, num_dcbs); - error = -EINVAL; - goto end_function; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] num_dcbs is %d\n", - current->pid, num_dcbs); - - /* Allocate thread-specific memory for DCB */ - *dcb_region = kzalloc(num_dcbs * sizeof(struct sep_dcblock), - GFP_KERNEL); - if (!(*dcb_region)) { - error = -ENOMEM; - goto end_function; - } - - /* Prepare DCB and MLLI table into the allocated regions */ - for (i = 0; i < num_dcbs; i++) { - error = sep_prepare_input_output_dma_table_in_dcb(sep, - (unsigned long)dcb_data->app_in_address, - (unsigned long)dcb_data->app_out_address, - dcb_data->data_in_size, - dcb_data->block_size, - dcb_data->tail_block_size, - dcb_data->is_applet, - true, - false, - *dcb_region, dmatables_region, - dma_ctx, - dcb_data->src_sg, - dcb_data->dst_sg); - if (error) { - dev_warn(&sep->pdev->dev, - "[PID%d] dma table creation failed\n", - current->pid); - goto end_function; - } - } - -end_function: - return error; -} - -/** - * sep_activate_msgarea_context - Takes the message area context into use - * @sep: SEP device - * @msg_region: Message area context buf - * @msg_len: Message area context buffer size - */ -static ssize_t sep_activate_msgarea_context(struct sep_device *sep, - void **msg_region, - const size_t msg_len) -{ - dev_dbg(&sep->pdev->dev, "[PID%d] activating msg region\n", - current->pid); - - if (!msg_region || !(*msg_region) || - SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES < msg_len) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid act msgarea len 0x%08zX\n", - current->pid, msg_len); - return -EINVAL; - } - - memcpy(sep->shared_addr, *msg_region, msg_len); - - return 0; -} - -/** - * sep_create_msgarea_context - Creates message area context - * @sep: SEP device - * @msg_region: Msg area region buf to create for current transaction - * @msg_user: Content for msg area region from user - * @msg_len: Message area size - */ -static ssize_t sep_create_msgarea_context(struct sep_device *sep, - void **msg_region, - const void __user *msg_user, - const size_t msg_len) -{ - int error = 0; - - dev_dbg(&sep->pdev->dev, "[PID%d] creating msg region\n", - current->pid); - - if (!msg_region || - !msg_user || - SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES < msg_len || - SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES > msg_len) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid creat msgarea len 0x%08zX\n", - current->pid, msg_len); - error = -EINVAL; - goto end_function; - } - - /* Allocate thread-specific memory for message buffer */ - *msg_region = kzalloc(msg_len, GFP_KERNEL); - if (!(*msg_region)) { - error = -ENOMEM; - goto end_function; - } - - /* Copy input data to write() to allocated message buffer */ - if (copy_from_user(*msg_region, msg_user, msg_len)) { - error = -EFAULT; - goto end_function; - } - -end_function: - if (error && msg_region) { - kfree(*msg_region); - *msg_region = NULL; - } - - return error; -} - -/** - * sep_read - Returns results of an operation for fastcall interface - * @filp: File pointer - * @buf_user: User buffer for storing results - * @count_user: User buffer size - * @offset: File offset, not supported - * - * The implementation does not support reading in chunks, all data must be - * consumed during a single read system call. - */ -static ssize_t sep_read(struct file *filp, - char __user *buf_user, size_t count_user, - loff_t *offset) -{ - struct sep_private_data * const private_data = filp->private_data; - struct sep_call_status *call_status = &private_data->call_status; - struct sep_device *sep = private_data->device; - struct sep_dma_context **dma_ctx = &private_data->dma_ctx; - struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; - ssize_t error = 0, error_tmp = 0; - - /* Am I the process that owns the transaction? */ - error = sep_check_transaction_owner(sep); - if (error) { - dev_dbg(&sep->pdev->dev, "[PID%d] read pid is not owner\n", - current->pid); - goto end_function; - } - - /* Checks that user has called necessary apis */ - if (0 == test_bit(SEP_FASTCALL_WRITE_DONE_OFFSET, - &call_status->status)) { - dev_warn(&sep->pdev->dev, - "[PID%d] fastcall write not called\n", - current->pid); - error = -EPROTO; - goto end_function_error; - } - - if (!buf_user) { - dev_warn(&sep->pdev->dev, - "[PID%d] null user buffer\n", - current->pid); - error = -EINVAL; - goto end_function_error; - } - - /* Wait for SEP to finish */ - wait_event(sep->event_interrupt, - test_bit(SEP_WORKING_LOCK_BIT, - &sep->in_use_flags) == 0); - - sep_dump_message(sep); - - dev_dbg(&sep->pdev->dev, "[PID%d] count_user = 0x%08zX\n", - current->pid, count_user); - - /* In case user has allocated bigger buffer */ - if (count_user > SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES) - count_user = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES; - - if (copy_to_user(buf_user, sep->shared_addr, count_user)) { - error = -EFAULT; - goto end_function_error; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] read succeeded\n", current->pid); - error = count_user; - -end_function_error: - /* Copy possible tail data to user and free DCB and MLLIs */ - error_tmp = sep_free_dcb_handler(sep, dma_ctx); - if (error_tmp) - dev_warn(&sep->pdev->dev, "[PID%d] dcb free failed\n", - current->pid); - - /* End the transaction, wakeup pending ones */ - error_tmp = sep_end_transaction_handler(sep, dma_ctx, call_status, - my_queue_elem); - if (error_tmp) - dev_warn(&sep->pdev->dev, - "[PID%d] ending transaction failed\n", - current->pid); - -end_function: - return error; -} - -/** - * sep_fastcall_args_get - Gets fastcall params from user - * sep: SEP device - * @args: Parameters buffer - * @buf_user: User buffer for operation parameters - * @count_user: User buffer size - */ -static inline ssize_t sep_fastcall_args_get(struct sep_device *sep, - struct sep_fastcall_hdr *args, - const char __user *buf_user, - const size_t count_user) -{ - ssize_t error = 0; - size_t actual_count = 0; - - if (!buf_user) { - dev_warn(&sep->pdev->dev, - "[PID%d] null user buffer\n", - current->pid); - error = -EINVAL; - goto end_function; - } - - if (count_user < sizeof(struct sep_fastcall_hdr)) { - dev_warn(&sep->pdev->dev, - "[PID%d] too small message size 0x%08zX\n", - current->pid, count_user); - error = -EINVAL; - goto end_function; - } - - if (copy_from_user(args, buf_user, sizeof(struct sep_fastcall_hdr))) { - error = -EFAULT; - goto end_function; - } - - if (SEP_FC_MAGIC != args->magic) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid fastcall magic 0x%08X\n", - current->pid, args->magic); - error = -EINVAL; - goto end_function; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] fastcall hdr num of DCBs 0x%08X\n", - current->pid, args->num_dcbs); - dev_dbg(&sep->pdev->dev, "[PID%d] fastcall hdr msg len 0x%08X\n", - current->pid, args->msg_len); - - if (SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES < args->msg_len || - SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES > args->msg_len) { - dev_warn(&sep->pdev->dev, - "[PID%d] invalid message length\n", - current->pid); - error = -EINVAL; - goto end_function; - } - - actual_count = sizeof(struct sep_fastcall_hdr) - + args->msg_len - + (args->num_dcbs * sizeof(struct build_dcb_struct)); - - if (actual_count != count_user) { - dev_warn(&sep->pdev->dev, - "[PID%d] inconsistent message sizes 0x%08zX vs 0x%08zX\n", - current->pid, actual_count, count_user); - error = -EMSGSIZE; - goto end_function; - } - -end_function: - return error; -} - -/** - * sep_write - Starts an operation for fastcall interface - * @filp: File pointer - * @buf_user: User buffer for operation parameters - * @count_user: User buffer size - * @offset: File offset, not supported - * - * The implementation does not support writing in chunks, - * all data must be given during a single write system call. - */ -static ssize_t sep_write(struct file *filp, - const char __user *buf_user, size_t count_user, - loff_t *offset) -{ - struct sep_private_data * const private_data = filp->private_data; - struct sep_call_status *call_status = &private_data->call_status; - struct sep_device *sep = private_data->device; - struct sep_dma_context *dma_ctx = NULL; - struct sep_fastcall_hdr call_hdr = {0}; - void *msg_region = NULL; - void *dmatables_region = NULL; - struct sep_dcblock *dcb_region = NULL; - ssize_t error = 0; - struct sep_queue_info *my_queue_elem = NULL; - bool my_secure_dma; /* are we using secure_dma (IMR)? */ - - dev_dbg(&sep->pdev->dev, "[PID%d] sep dev is 0x%p\n", - current->pid, sep); - dev_dbg(&sep->pdev->dev, "[PID%d] private_data is 0x%p\n", - current->pid, private_data); - - error = sep_fastcall_args_get(sep, &call_hdr, buf_user, count_user); - if (error) - goto end_function; - - buf_user += sizeof(struct sep_fastcall_hdr); - - if (call_hdr.secure_dma == 0) - my_secure_dma = false; - else - my_secure_dma = true; - - /* - * Controlling driver memory usage by limiting amount of - * buffers created. Only SEP_DOUBLEBUF_USERS_LIMIT number - * of threads can progress further at a time - */ - dev_dbg(&sep->pdev->dev, - "[PID%d] waiting for double buffering region access\n", - current->pid); - error = down_interruptible(&sep->sep_doublebuf); - dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region start\n", - current->pid); - if (error) { - /* Signal received */ - goto end_function_error; - } - - /* - * Prepare contents of the shared area regions for - * the operation into temporary buffers - */ - if (0 < call_hdr.num_dcbs) { - error = sep_create_dcb_dmatables_context(sep, - &dcb_region, - &dmatables_region, - &dma_ctx, - (const struct build_dcb_struct __user *) - buf_user, - call_hdr.num_dcbs, my_secure_dma); - if (error) - goto end_function_error_doublebuf; - - buf_user += call_hdr.num_dcbs * sizeof(struct build_dcb_struct); - } - - error = sep_create_msgarea_context(sep, - &msg_region, - buf_user, - call_hdr.msg_len); - if (error) - goto end_function_error_doublebuf; - - dev_dbg(&sep->pdev->dev, "[PID%d] updating queue status\n", - current->pid); - my_queue_elem = sep_queue_status_add(sep, - ((struct sep_msgarea_hdr *)msg_region)->opcode, - (dma_ctx) ? dma_ctx->input_data_len : 0, - current->pid, - current->comm, sizeof(current->comm)); - - if (!my_queue_elem) { - dev_dbg(&sep->pdev->dev, - "[PID%d] updating queue status error\n", current->pid); - error = -ENOMEM; - goto end_function_error_doublebuf; - } - - /* Wait until current process gets the transaction */ - error = sep_wait_transaction(sep); - - if (error) { - /* Interrupted by signal, don't clear transaction */ - dev_dbg(&sep->pdev->dev, "[PID%d] interrupted by signal\n", - current->pid); - sep_queue_status_remove(sep, &my_queue_elem); - goto end_function_error_doublebuf; - } - - dev_dbg(&sep->pdev->dev, "[PID%d] saving queue element\n", - current->pid); - private_data->my_queue_elem = my_queue_elem; - - /* Activate shared area regions for the transaction */ - error = sep_activate_msgarea_context(sep, &msg_region, - call_hdr.msg_len); - if (error) - goto end_function_error_clear_transact; - - sep_dump_message(sep); - - if (0 < call_hdr.num_dcbs) { - error = sep_activate_dcb_dmatables_context(sep, - &dcb_region, - &dmatables_region, - dma_ctx); - if (error) - goto end_function_error_clear_transact; - } - - /* Send command to SEP */ - error = sep_send_command_handler(sep); - if (error) - goto end_function_error_clear_transact; - - /* Store DMA context for the transaction */ - private_data->dma_ctx = dma_ctx; - /* Update call status */ - set_bit(SEP_FASTCALL_WRITE_DONE_OFFSET, &call_status->status); - error = count_user; - - up(&sep->sep_doublebuf); - dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region end\n", - current->pid); - - goto end_function; - -end_function_error_clear_transact: - sep_end_transaction_handler(sep, &dma_ctx, call_status, - &private_data->my_queue_elem); - -end_function_error_doublebuf: - up(&sep->sep_doublebuf); - dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region end\n", - current->pid); - -end_function_error: - if (dma_ctx) - sep_free_dma_table_data_handler(sep, &dma_ctx); - -end_function: - kfree(dcb_region); - kfree(dmatables_region); - kfree(msg_region); - - return error; -} - -/** - * sep_seek - Handler for seek system call - * @filp: File pointer - * @offset: File offset - * @origin: Options for offset - * - * Fastcall interface does not support seeking, all reads - * and writes are from/to offset zero - */ -static loff_t sep_seek(struct file *filp, loff_t offset, int origin) -{ - return -ENOSYS; -} - -/** - * sep_file_operations - file operation on sep device - * @sep_ioctl: ioctl handler from user space call - * @sep_poll: poll handler - * @sep_open: handles sep device open request - * @sep_release:handles sep device release request - * @sep_mmap: handles memory mapping requests - * @sep_read: handles read request on sep device - * @sep_write: handles write request on sep device - * @sep_seek: handles seek request on sep device - */ -static const struct file_operations sep_file_operations = { - .owner = THIS_MODULE, - .unlocked_ioctl = sep_ioctl, - .poll = sep_poll, - .open = sep_open, - .release = sep_release, - .mmap = sep_mmap, - .read = sep_read, - .write = sep_write, - .llseek = sep_seek, -}; - -/** - * sep_sysfs_read - read sysfs entry per gives arguments - * @filp: file pointer - * @kobj: kobject pointer - * @attr: binary file attributes - * @buf: read to this buffer - * @pos: offset to read - * @count: amount of data to read - * - * This function is to read sysfs entries for sep driver per given arguments. - */ -static ssize_t -sep_sysfs_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t pos, size_t count) -{ - unsigned long lck_flags; - size_t nleft = count; - struct sep_device *sep = sep_dev; - struct sep_queue_info *queue_elem = NULL; - u32 queue_num = 0; - u32 i = 1; - - spin_lock_irqsave(&sep->sep_queue_lock, lck_flags); - - queue_num = sep->sep_queue_num; - if (queue_num > SEP_DOUBLEBUF_USERS_LIMIT) - queue_num = SEP_DOUBLEBUF_USERS_LIMIT; - - if (count < sizeof(queue_num) - + (queue_num * sizeof(struct sep_queue_data))) { - spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); - return -EINVAL; - } - - memcpy(buf, &queue_num, sizeof(queue_num)); - buf += sizeof(queue_num); - nleft -= sizeof(queue_num); - - list_for_each_entry(queue_elem, &sep->sep_queue_status, list) { - if (i++ > queue_num) - break; - - memcpy(buf, &queue_elem->data, sizeof(queue_elem->data)); - nleft -= sizeof(queue_elem->data); - buf += sizeof(queue_elem->data); - } - spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); - - return count - nleft; -} - -/** - * bin_attributes - defines attributes for queue_status - * @attr: attributes (name & permissions) - * @read: function pointer to read this file - * @size: maxinum size of binary attribute - */ -static const struct bin_attribute queue_status = { - .attr = {.name = "queue_status", .mode = 0444}, - .read = sep_sysfs_read, - .size = sizeof(u32) - + (SEP_DOUBLEBUF_USERS_LIMIT * sizeof(struct sep_queue_data)), -}; - -/** - * sep_register_driver_with_fs - register misc devices - * @sep: pointer to struct sep_device - * - * This function registers the driver with the file system - */ -static int sep_register_driver_with_fs(struct sep_device *sep) -{ - int ret_val; - - sep->miscdev_sep.minor = MISC_DYNAMIC_MINOR; - sep->miscdev_sep.name = SEP_DEV_NAME; - sep->miscdev_sep.fops = &sep_file_operations; - - ret_val = misc_register(&sep->miscdev_sep); - if (ret_val) { - dev_warn(&sep->pdev->dev, "misc reg fails for SEP %x\n", - ret_val); - return ret_val; - } - - ret_val = device_create_bin_file(sep->miscdev_sep.this_device, - &queue_status); - if (ret_val) { - dev_warn(&sep->pdev->dev, "sysfs attribute1 fails for SEP %x\n", - ret_val); - misc_deregister(&sep->miscdev_sep); - return ret_val; - } - - return ret_val; -} - -/** - *sep_probe - probe a matching PCI device - *@pdev: pci_device - *@ent: pci_device_id - * - *Attempt to set up and configure a SEP device that has been - *discovered by the PCI layer. Allocates all required resources. - */ -static int sep_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int error = 0; - struct sep_device *sep = NULL; - - if (sep_dev != NULL) { - dev_dbg(&pdev->dev, "only one SEP supported.\n"); - return -EBUSY; - } - - /* Enable the device */ - error = pci_enable_device(pdev); - if (error) { - dev_warn(&pdev->dev, "error enabling pci device\n"); - goto end_function; - } - - /* Allocate the sep_device structure for this device */ - sep_dev = kzalloc(sizeof(struct sep_device), GFP_ATOMIC); - if (sep_dev == NULL) { - error = -ENOMEM; - goto end_function_disable_device; - } - - /* - * We're going to use another variable for actually - * working with the device; this way, if we have - * multiple devices in the future, it would be easier - * to make appropriate changes - */ - sep = sep_dev; - - sep->pdev = pci_dev_get(pdev); - - init_waitqueue_head(&sep->event_transactions); - init_waitqueue_head(&sep->event_interrupt); - spin_lock_init(&sep->snd_rply_lck); - spin_lock_init(&sep->sep_queue_lock); - sema_init(&sep->sep_doublebuf, SEP_DOUBLEBUF_USERS_LIMIT); - - INIT_LIST_HEAD(&sep->sep_queue_status); - - dev_dbg(&sep->pdev->dev, - "sep probe: PCI obtained, device being prepared\n"); - - /* Set up our register area */ - sep->reg_physical_addr = pci_resource_start(sep->pdev, 0); - if (!sep->reg_physical_addr) { - dev_warn(&sep->pdev->dev, "Error getting register start\n"); - error = -ENODEV; - goto end_function_free_sep_dev; - } - - sep->reg_physical_end = pci_resource_end(sep->pdev, 0); - if (!sep->reg_physical_end) { - dev_warn(&sep->pdev->dev, "Error getting register end\n"); - error = -ENODEV; - goto end_function_free_sep_dev; - } - - sep->reg_addr = ioremap_nocache(sep->reg_physical_addr, - (size_t)(sep->reg_physical_end - sep->reg_physical_addr + 1)); - if (!sep->reg_addr) { - dev_warn(&sep->pdev->dev, "Error getting register virtual\n"); - error = -ENODEV; - goto end_function_free_sep_dev; - } - - dev_dbg(&sep->pdev->dev, - "Register area start %llx end %llx virtual %p\n", - (unsigned long long)sep->reg_physical_addr, - (unsigned long long)sep->reg_physical_end, - sep->reg_addr); - - /* Allocate the shared area */ - sep->shared_size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES + - SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + - SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + - SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES; - - if (sep_map_and_alloc_shared_area(sep)) { - error = -ENOMEM; - /* Allocation failed */ - goto end_function_error; - } - - /* Clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - - /* Set the IMR register - open only GPR 2 */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); - - /* Read send/receive counters from SEP */ - sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - sep->reply_ct &= 0x3FFFFFFF; - sep->send_ct = sep->reply_ct; - - /* Get the interrupt line */ - error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED, - "sep_driver", sep); - - if (error) - goto end_function_deallocate_sep_shared_area; - - /* The new chip requires a shared area reconfigure */ - error = sep_reconfig_shared_area(sep); - if (error) - goto end_function_free_irq; - - sep->in_use = 1; - - /* Finally magic up the device nodes */ - /* Register driver with the fs */ - error = sep_register_driver_with_fs(sep); - - if (error) { - dev_err(&sep->pdev->dev, "error registering dev file\n"); - goto end_function_free_irq; - } - - sep->in_use = 0; /* through touching the device */ -#ifdef SEP_ENABLE_RUNTIME_PM - pm_runtime_put_noidle(&sep->pdev->dev); - pm_runtime_allow(&sep->pdev->dev); - pm_runtime_set_autosuspend_delay(&sep->pdev->dev, - SUSPEND_DELAY); - pm_runtime_use_autosuspend(&sep->pdev->dev); - pm_runtime_mark_last_busy(&sep->pdev->dev); - sep->power_save_setup = 1; -#endif - /* register kernel crypto driver */ -#if defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) - error = sep_crypto_setup(); - if (error) { - dev_err(&sep->pdev->dev, "crypto setup failed\n"); - goto end_function_free_irq; - } -#endif - goto end_function; - -end_function_free_irq: - free_irq(pdev->irq, sep); - -end_function_deallocate_sep_shared_area: - /* De-allocate shared area */ - sep_unmap_and_free_shared_area(sep); - -end_function_error: - iounmap(sep->reg_addr); - -end_function_free_sep_dev: - pci_dev_put(sep_dev->pdev); - kfree(sep_dev); - sep_dev = NULL; - -end_function_disable_device: - pci_disable_device(pdev); - -end_function: - return error; -} - -/** - * sep_remove - handles removing device from pci subsystem - * @pdev: pointer to pci device - * - * This function will handle removing our sep device from pci subsystem on exit - * or unloading this module. It should free up all used resources, and unmap if - * any memory regions mapped. - */ -static void sep_remove(struct pci_dev *pdev) -{ - struct sep_device *sep = sep_dev; - - /* Unregister from fs */ - misc_deregister(&sep->miscdev_sep); - - /* Unregister from kernel crypto */ -#if defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) - sep_crypto_takedown(); -#endif - /* Free the irq */ - free_irq(sep->pdev->irq, sep); - - /* Free the shared area */ - sep_unmap_and_free_shared_area(sep_dev); - iounmap(sep_dev->reg_addr); - -#ifdef SEP_ENABLE_RUNTIME_PM - if (sep->in_use) { - sep->in_use = 0; - pm_runtime_forbid(&sep->pdev->dev); - pm_runtime_get_noresume(&sep->pdev->dev); - } -#endif - pci_dev_put(sep_dev->pdev); - kfree(sep_dev); - sep_dev = NULL; -} - -/* Initialize struct pci_device_id for our driver */ -static const struct pci_device_id sep_pci_id_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0826)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08e9)}, - {0} -}; - -/* Export our pci_device_id structure to user space */ -MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl); - -#ifdef SEP_ENABLE_RUNTIME_PM - -/** - * sep_pm_resume - rsume routine while waking up from S3 state - * @dev: pointer to sep device - * - * This function is to be used to wake up sep driver while system awakes from S3 - * state i.e. suspend to ram. The RAM in intact. - * Notes - revisit with more understanding of pm, ICR/IMR & counters. - */ -static int sep_pci_resume(struct device *dev) -{ - struct sep_device *sep = sep_dev; - - dev_dbg(&sep->pdev->dev, "pci resume called\n"); - - if (sep->power_state == SEP_DRIVER_POWERON) - return 0; - - /* Clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - - /* Set the IMR register - open only GPR 2 */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); - - /* Read send/receive counters from SEP */ - sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - sep->reply_ct &= 0x3FFFFFFF; - sep->send_ct = sep->reply_ct; - - sep->power_state = SEP_DRIVER_POWERON; - - return 0; -} - -/** - * sep_pm_suspend - suspend routine while going to S3 state - * @dev: pointer to sep device - * - * This function is to be used to suspend sep driver while system goes to S3 - * state i.e. suspend to ram. The RAM in intact and ON during this suspend. - * Notes - revisit with more understanding of pm, ICR/IMR - */ -static int sep_pci_suspend(struct device *dev) -{ - struct sep_device *sep = sep_dev; - - dev_dbg(&sep->pdev->dev, "pci suspend called\n"); - if (sep->in_use == 1) - return -EAGAIN; - - sep->power_state = SEP_DRIVER_POWEROFF; - - /* Clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - - /* Set the IMR to block all */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0xFFFFFFFF); - - return 0; -} - -/** - * sep_pm_runtime_resume - runtime resume routine - * @dev: pointer to sep device - * - * Notes - revisit with more understanding of pm, ICR/IMR & counters - */ -static int sep_pm_runtime_resume(struct device *dev) -{ - u32 retval2; - u32 delay_count; - struct sep_device *sep = sep_dev; - - dev_dbg(&sep->pdev->dev, "pm runtime resume called\n"); - - /** - * Wait until the SCU boot is ready - * This is done by iterating SCU_DELAY_ITERATION (10 - * microseconds each) up to SCU_DELAY_MAX (50) times. - * This bit can be set in a random time that is less - * than 500 microseconds after each power resume - */ - retval2 = 0; - delay_count = 0; - while ((!retval2) && (delay_count < SCU_DELAY_MAX)) { - retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); - retval2 &= 0x00000008; - if (!retval2) { - udelay(SCU_DELAY_ITERATION); - delay_count += 1; - } - } - - if (!retval2) { - dev_warn(&sep->pdev->dev, "scu boot bit not set at resume\n"); - return -EINVAL; - } - - /* Clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - - /* Set the IMR register - open only GPR 2 */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); - - /* Read send/receive counters from SEP */ - sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - sep->reply_ct &= 0x3FFFFFFF; - sep->send_ct = sep->reply_ct; - - return 0; -} - -/** - * sep_pm_runtime_suspend - runtime suspend routine - * @dev: pointer to sep device - * - * Notes - revisit with more understanding of pm - */ -static int sep_pm_runtime_suspend(struct device *dev) -{ - struct sep_device *sep = sep_dev; - - dev_dbg(&sep->pdev->dev, "pm runtime suspend called\n"); - - /* Clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - return 0; -} - -/** - * sep_pm - power management for sep driver - * @sep_pm_runtime_resume: resume- no communication with cpu & main memory - * @sep_pm_runtime_suspend: suspend- no communication with cpu & main memory - * @sep_pci_suspend: suspend - main memory is still ON - * @sep_pci_resume: resume - main memory is still ON - */ -static const struct dev_pm_ops sep_pm = { - .runtime_resume = sep_pm_runtime_resume, - .runtime_suspend = sep_pm_runtime_suspend, - .resume = sep_pci_resume, - .suspend = sep_pci_suspend, -}; -#endif /* SEP_ENABLE_RUNTIME_PM */ - -/** - * sep_pci_driver - registers this device with pci subsystem - * @name: name identifier for this driver - * @sep_pci_id_tbl: pointer to struct pci_device_id table - * @sep_probe: pointer to probe function in PCI driver - * @sep_remove: pointer to remove function in PCI driver - */ -static struct pci_driver sep_pci_driver = { -#ifdef SEP_ENABLE_RUNTIME_PM - .driver = { - .pm = &sep_pm, - }, -#endif - .name = "sep_sec_driver", - .id_table = sep_pci_id_tbl, - .probe = sep_probe, - .remove = sep_remove -}; - -module_pci_driver(sep_pci_driver); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/sep/sep_trace_events.h b/drivers/staging/sep/sep_trace_events.h deleted file mode 100644 index 74f4c9a2b5be..000000000000 --- a/drivers/staging/sep/sep_trace_events.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * If TRACE_SYSTEM is defined, that will be the directory created - * in the ftrace directory under /sys/kernel/debug/tracing/events/ - * - * The define_trace.h below will also look for a file name of - * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. - * In this case, it would look for sample.h - * - * If the header name will be different than the system name - * (as in this case), then you can override the header name that - * define_trace.h will look up by defining TRACE_INCLUDE_FILE - * - * This file is called trace-events-sample.h but we want the system - * to be called "sample". Therefore we must define the name of this - * file: - * - * #define TRACE_INCLUDE_FILE trace-events-sample - * - * As we do an the bottom of this file. - * - * Notice that TRACE_SYSTEM should be defined outside of #if - * protection, just like TRACE_INCLUDE_FILE. - */ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM sep - -/* - * Notice that this file is not protected like a normal header. - * We also must allow for rereading of this file. The - * - * || defined(TRACE_HEADER_MULTI_READ) - * - * serves this purpose. - */ -#if !defined(_TRACE_SEP_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_SEP_EVENTS_H - -#ifdef SEP_PERF_DEBUG -#define SEP_TRACE_FUNC_IN() trace_sep_func_start(__func__, 0) -#define SEP_TRACE_FUNC_OUT(branch) trace_sep_func_end(__func__, branch) -#define SEP_TRACE_EVENT(branch) trace_sep_misc_event(__func__, branch) -#else -#define SEP_TRACE_FUNC_IN() -#define SEP_TRACE_FUNC_OUT(branch) -#define SEP_TRACE_EVENT(branch) -#endif - - -/* - * All trace headers should include tracepoint.h, until we finally - * make it into a standard header. - */ -#include - -/* - * Since use str*cpy in header file, better to include string.h, directly. - */ -#include - -/* - * The TRACE_EVENT macro is broken up into 5 parts. - * - * name: name of the trace point. This is also how to enable the tracepoint. - * A function called trace_foo_bar() will be created. - * - * proto: the prototype of the function trace_foo_bar() - * Here it is trace_foo_bar(char *foo, int bar). - * - * args: must match the arguments in the prototype. - * Here it is simply "foo, bar". - * - * struct: This defines the way the data will be stored in the ring buffer. - * There are currently two types of elements. __field and __array. - * a __field is broken up into (type, name). Where type can be any - * type but an array. - * For an array. there are three fields. (type, name, size). The - * type of elements in the array, the name of the field and the size - * of the array. - * - * __array( char, foo, 10) is the same as saying char foo[10]. - * - * fast_assign: This is a C like function that is used to store the items - * into the ring buffer. - * - * printk: This is a way to print out the data in pretty print. This is - * useful if the system crashes and you are logging via a serial line, - * the data can be printed to the console using this "printk" method. - * - * Note, that for both the assign and the printk, __entry is the handler - * to the data structure in the ring buffer, and is defined by the - * TP_STRUCT__entry. - */ -TRACE_EVENT(sep_func_start, - - TP_PROTO(const char *name, int branch), - - TP_ARGS(name, branch), - - TP_STRUCT__entry( - __array(char, name, 20) - __field(int, branch) - ), - - TP_fast_assign( - strlcpy(__entry->name, name, 20); - __entry->branch = branch; - ), - - TP_printk("func_start %s %d", __entry->name, __entry->branch) -); - -TRACE_EVENT(sep_func_end, - - TP_PROTO(const char *name, int branch), - - TP_ARGS(name, branch), - - TP_STRUCT__entry( - __array(char, name, 20) - __field(int, branch) - ), - - TP_fast_assign( - strlcpy(__entry->name, name, 20); - __entry->branch = branch; - ), - - TP_printk("func_end %s %d", __entry->name, __entry->branch) -); - -TRACE_EVENT(sep_misc_event, - - TP_PROTO(const char *name, int branch), - - TP_ARGS(name, branch), - - TP_STRUCT__entry( - __array(char, name, 20) - __field(int, branch) - ), - - TP_fast_assign( - strlcpy(__entry->name, name, 20); - __entry->branch = branch; - ), - - TP_printk("misc_event %s %d", __entry->name, __entry->branch) -); - - -#endif - -/***** NOTICE! The #if protection ends here. *****/ - - -/* - * There are several ways I could have done this. If I left out the - * TRACE_INCLUDE_PATH, then it would default to the kernel source - * include/trace/events directory. - * - * I could specify a path from the define_trace.h file back to this - * file. - * - * #define TRACE_INCLUDE_PATH ../../samples/trace_events - * - * But the safest and easiest way to simply make it use the directory - * that the file is in is to add in the Makefile: - * - * CFLAGS_trace-events-sample.o := -I$(src) - * - * This will make sure the current path is part of the include - * structure for our file so that define_trace.h can find it. - * - * I could have made only the top level directory the include: - * - * CFLAGS_trace-events-sample.o := -I$(PWD) - * - * And then let the path to this directory be the TRACE_INCLUDE_PATH: - * - * #define TRACE_INCLUDE_PATH samples/trace_events - * - * But then if something defines "samples" or "trace_events" as a macro - * then we could risk that being converted too, and give us an unexpected - * result. - */ -#undef TRACE_INCLUDE_PATH -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_PATH . -/* - * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal - */ -#define TRACE_INCLUDE_FILE sep_trace_events -#include -- 2.30.2