3 * sep_main_mod.c - Security Processor Driver main group of functions
5 * Copyright(c) 2009 Intel Corporation. All rights reserved.
6 * Copyright(c) 2009 Discretix. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Mark Allyn mark.a.allyn@intel.com
28 * 2009.06.26 Initial publish
32 #include <linux/init.h>
33 #include <linux/module.h>
35 #include <linux/cdev.h>
36 #include <linux/kdev_t.h>
37 #include <linux/mutex.h>
39 #include <linux/poll.h>
40 #include <linux/wait.h>
41 #include <asm/ioctl.h>
42 #include <linux/ioport.h>
44 #include <linux/interrupt.h>
45 #include <linux/pagemap.h>
46 #include <asm/cacheflush.h>
47 #include "sep_driver_hw_defs.h"
48 #include "sep_driver_config.h"
49 #include "sep_driver_api.h"
50 #include "sep_driver_ext_api.h"
53 /*----------------------------------------
55 -----------------------------------------*/
58 #define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
60 /*--------------------------------------
62 -----------------------------------------*/
66 /*--------------------------------------------
68 --------------------------------------------*/
70 /* debug messages level */
71 INT_MODULE_PARM(sepDebug, 0x0);
72 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
74 /* major and minor device numbers */
75 static dev_t g_sep_device_number;
77 /* the files operations structure of the driver */
78 static struct file_operations g_sep_fops;
80 /* cdev struct of the driver */
81 static struct cdev g_sep_cdev;
84 mutex for the access to the internals of the sep driver
86 static DEFINE_MUTEX(sep_mutex);
89 /* wait queue head (event) of the driver */
90 static DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
94 /*------------------------------------------------
96 ---------------------------------------------------*/
99 interrupt handler function
101 irqreturn_t sep_inthandler(int irq, void *dev_id);
104 this function registers the driver to the file system
106 static int sep_register_driver_to_fs(void);
109 this function unregisters driver from fs
111 static void sep_unregister_driver_from_fs(void);
114 this function calculates the size of data that can be inserted into the lli
115 table from this array the condition is that either the table is full
116 (all etnries are entered), or there are no more entries in the lli array
118 static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries);
120 this functions builds ont lli table from the lli_array according to the
123 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr, struct sep_lli_entry_t *lli_table_ptr, unsigned long *num_processed_entries_ptr, unsigned long *num_table_entries_ptr, unsigned long table_data_size);
126 this function goes over the list of the print created tables and prints
129 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size);
134 This function raises interrupt to SEPm that signals that is has a new
137 static void sep_send_command_handler(void);
141 This function raises interrupt to SEP that signals that is has a
144 static void sep_send_reply_command_handler(void);
147 This function handles the allocate data pool memory request
148 This function returns calculates the physical address of the allocated memory
149 and the offset of this area from the mapped address. Therefore, the FVOs in
150 user space can calculate the exact virtual address of this allocated memory
152 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
156 This function handles write into allocated data pool command
158 static int sep_write_into_data_pool_handler(unsigned long arg);
161 this function handles the read from data pool command
163 static int sep_read_from_data_pool_handler(unsigned long arg);
166 this function handles tha request for creation of the DMA table
167 for the synchronic symmetric operations (AES,DES)
169 static int sep_create_sync_dma_tables_handler(unsigned long arg);
172 this function handles the request to create the DMA tables for flow
174 static int sep_create_flow_dma_tables_handler(unsigned long arg);
177 This API handles the end transaction request
179 static int sep_end_transaction_handler(unsigned long arg);
183 this function handles add tables to flow
185 static int sep_add_flow_tables_handler(unsigned long arg);
188 this function add the flow add message to the specific flow
190 static int sep_add_flow_tables_message_handler(unsigned long arg);
193 this function handles the request for SEP start
195 static int sep_start_handler(void);
198 this function handles the request for SEP initialization
200 static int sep_init_handler(unsigned long arg);
203 this function handles the request cache and resident reallocation
205 static int sep_realloc_cache_resident_handler(unsigned long arg);
209 This api handles the setting of API mode to blocking or non-blocking
211 static int sep_set_api_mode_handler(unsigned long arg);
213 /* handler for flow done interrupt */
214 static void sep_flow_done_handler(struct work_struct *work);
217 This function locks all the physical pages of the kernel virtual buffer
218 and construct a basic lli array, where each entry holds the physical
219 page address and the size that application data holds in this physical pages
221 static int sep_lock_kernel_pages(unsigned long kernel_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr);
224 This function creates one DMA table for flow and returns its data,
225 and pointer to its info entry
227 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr, unsigned long virt_buff_size, struct sep_lli_entry_t *table_data, struct sep_lli_entry_t **info_entry_ptr, struct sep_flow_context_t *flow_data_ptr, bool isKernelVirtualAddress);
230 This function creates a list of tables for flow and returns the data for the
231 first and last tables of the list
233 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
234 unsigned long first_buff_addr, struct sep_flow_context_t *flow_data_ptr, struct sep_lli_entry_t *first_table_data_ptr, struct sep_lli_entry_t *last_table_data_ptr, bool isKernelVirtualAddress);
237 this function find a space for the new flow dma table
239 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr);
242 this function goes over all the flow tables connected to the given table and
245 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr);
248 This function handler the set flow id command
250 static int sep_set_flow_id_handler(unsigned long arg);
253 This function returns pointer to the flow data structure
254 that conatins the given id
256 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr);
260 this function returns the physical and virtual addresses of the static pool
262 static int sep_get_static_pool_addr_handler(unsigned long arg);
265 this address gets the offset of the physical address from the start of
268 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
272 this function handles the request for get time
274 static int sep_get_time_handler(unsigned long arg);
277 calculates time and sets it at the predefined address
279 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr);
282 PATCH for configuring the DMA to single burst instead of multi-burst
284 static void sep_configure_dma_burst(void);
287 This function locks all the physical pages of the
288 application virtual buffer and construct a basic lli
289 array, where each entry holds the physical page address
290 and the size that application data holds in this physical pages
292 static int sep_lock_user_pages(unsigned long app_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr);
294 /*---------------------------------------------
296 -----------------------------------------------*/
299 this function locks SEP by locking the semaphore
303 mutex_lock(&sep_mutex);
308 this function unlocks SEP
313 mutex_unlock(&sep_mutex);
317 this function returns the address of the message shared area
319 void sep_map_shared_area(unsigned long *mappedAddr_ptr)
321 *mappedAddr_ptr = sep_dev->shared_area_addr;
325 this function returns the address of the message shared area
327 void sep_send_msg_rdy_cmd()
329 sep_send_command_handler();
332 /* this functions frees all the resources that were allocated for the building
333 of the LLI DMA tables */
334 void sep_free_dma_resources()
336 sep_free_dma_table_data_handler();
339 /* poll(suspend), until reply from sep */
340 void sep_driver_poll()
342 unsigned long retVal = 0;
344 #ifdef SEP_DRIVER_POLLING_MODE
346 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
347 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
349 sep_dev->sep_to_host_reply_counter++;
351 /* poll, until reply from sep */
352 wait_event(g_sep_event, (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
357 /*----------------------------------------------------------------------
358 open function of the character driver - must only lock the mutex
359 must also release the memory data pool allocations
360 ------------------------------------------------------------------------*/
361 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
365 dbg("SEP Driver:--------> open start\n");
369 /* check the blocking mode */
370 if (sep_dev->block_mode_flag)
372 mutex_lock(&sep_mutex);
374 error = mutex_trylock(&sep_mutex);
376 /* check the error */
378 edbg("SEP Driver: down_interruptible failed\n");
383 /* release data pool allocations */
384 sep_dev->data_pool_bytes_allocated = 0;
387 dbg("SEP Driver:<-------- open end\n");
394 /*------------------------------------------------------------
396 -------------------------------------------------------------*/
397 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
399 dbg("----------->SEP Driver: sep_release start\n");
401 #if 0 /*!SEP_DRIVER_POLLING_MODE */
403 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
405 /* release IRQ line */
406 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
410 /* unlock the sep mutex */
411 mutex_unlock(&sep_mutex);
413 dbg("SEP Driver:<-------- sep_release end\n");
421 /*---------------------------------------------------------------
422 map function - this functions maps the message shared area
423 -----------------------------------------------------------------*/
424 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
426 unsigned long phys_addr;
428 dbg("-------->SEP Driver: mmap start\n");
430 /* check that the size of the mapped range is as the size of the message
432 if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
433 edbg("SEP Driver mmap requested size is more than allowed\n");
434 printk(KERN_WARNING "SEP Driver mmap requested size is more \
436 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
437 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
441 edbg("SEP Driver:g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
443 /* get physical address */
444 phys_addr = sep_dev->phys_shared_area_addr;
446 edbg("SEP Driver: phys_addr is %08lx\n", phys_addr);
448 if (remap_pfn_range(vma, vma->vm_start, phys_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
449 edbg("SEP Driver remap_page_range failed\n");
450 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
454 dbg("SEP Driver:<-------- mmap end\n");
460 /*-----------------------------------------------
462 *----------------------------------------------*/
463 static unsigned int sep_poll(struct file *filp, poll_table * wait)
466 unsigned int mask = 0;
467 unsigned long retVal = 0; /* flow id */
469 dbg("---------->SEP Driver poll: start\n");
472 #if SEP_DRIVER_POLLING_MODE
474 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
475 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
477 for (count = 0; count < 10 * 4; count += 4)
478 edbg("Poll Debug Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
481 sep_dev->sep_to_host_reply_counter++;
483 /* add the event to the polling wait table */
484 poll_wait(filp, &g_sep_event, wait);
488 edbg("sep_dev->host_to_sep_send_counter is %lu\n", sep_dev->host_to_sep_send_counter);
489 edbg("sep_dev->sep_to_host_reply_counter is %lu\n", sep_dev->sep_to_host_reply_counter);
491 /* check if the data is ready */
492 if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
493 for (count = 0; count < 12 * 4; count += 4)
494 edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
496 for (count = 0; count < 10 * 4; count += 4)
497 edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + 0x1800 + count)));
499 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
500 edbg("retVal is %lu\n", retVal);
501 /* check if the this is sep reply or request */
503 edbg("SEP Driver: sep request in\n");
505 mask |= POLLOUT | POLLWRNORM;
507 edbg("SEP Driver: sep reply in\n");
508 mask |= POLLIN | POLLRDNORM;
511 dbg("SEP Driver:<-------- poll exit\n");
516 static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
520 dbg("------------>SEP Driver: ioctl start\n");
522 edbg("SEP Driver: cmd is %x\n", cmd);
524 /* check that the command is for sep device */
525 if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
529 case SEP_IOCSENDSEPCOMMAND:
530 /* send command to SEP */
531 sep_send_command_handler();
532 edbg("SEP Driver: after sep_send_command_handler\n");
534 case SEP_IOCSENDSEPRPLYCOMMAND:
535 /* send reply command to SEP */
536 sep_send_reply_command_handler();
538 case SEP_IOCALLOCDATAPOLL:
539 /* allocate data pool */
540 error = sep_allocate_data_pool_memory_handler(arg);
542 case SEP_IOCWRITEDATAPOLL:
543 /* write data into memory pool */
544 error = sep_write_into_data_pool_handler(arg);
546 case SEP_IOCREADDATAPOLL:
547 /* read data from data pool into application memory */
548 error = sep_read_from_data_pool_handler(arg);
550 case SEP_IOCCREATESYMDMATABLE:
551 /* create dma table for synhronic operation */
552 error = sep_create_sync_dma_tables_handler(arg);
554 case SEP_IOCCREATEFLOWDMATABLE:
555 /* create flow dma tables */
556 error = sep_create_flow_dma_tables_handler(arg);
558 case SEP_IOCFREEDMATABLEDATA:
560 error = sep_free_dma_table_data_handler();
562 case SEP_IOCSETFLOWID:
564 error = sep_set_flow_id_handler(arg);
566 case SEP_IOCADDFLOWTABLE:
567 /* add tables to the dynamic flow */
568 error = sep_add_flow_tables_handler(arg);
570 case SEP_IOCADDFLOWMESSAGE:
571 /* add message of add tables to flow */
572 error = sep_add_flow_tables_message_handler(arg);
574 case SEP_IOCSEPSTART:
575 /* start command to sep */
576 error = sep_start_handler();
579 /* init command to sep */
580 error = sep_init_handler(arg);
582 case SEP_IOCSETAPIMODE:
583 /* set non- blocking mode */
584 error = sep_set_api_mode_handler(arg);
586 case SEP_IOCGETSTATICPOOLADDR:
587 /* get the physical and virtual addresses of the static pool */
588 error = sep_get_static_pool_addr_handler(arg);
590 case SEP_IOCENDTRANSACTION:
591 error = sep_end_transaction_handler(arg);
593 case SEP_IOCREALLOCCACHERES:
594 error = sep_realloc_cache_resident_handler(arg);
596 case SEP_IOCGETMAPPEDADDROFFSET:
597 error = sep_get_physical_mapped_offset_handler(arg);
600 error = sep_get_time_handler(arg);
606 dbg("SEP Driver:<-------- ioctl end\n");
613 interrupt handler function
615 irqreturn_t sep_inthandler(int irq, void *dev_id)
617 irqreturn_t int_error;
619 unsigned long reg_val;
620 unsigned long flow_id;
621 struct sep_flow_context_t *flow_context_ptr;
623 int_error = IRQ_HANDLED;
625 /* read the IRR register to check if this is SEP interrupt */
626 reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
627 edbg("SEP Interrupt - reg is %08lx\n", reg_val);
629 /* check if this is the flow interrupt */
630 if (0 /*reg_val & (0x1 << 11) */ ) {
631 /* read GPRO to find out the which flow is done */
632 flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
634 /* find the contex of the flow */
635 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
637 goto end_function_with_error;
639 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
642 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
645 /* check if this is reply interrupt from SEP */
646 if (reg_val & (0x1 << 13)) {
647 /* update the counter of reply messages */
648 sep_dev->sep_to_host_reply_counter++;
650 /* wake up the waiting process */
651 wake_up(&g_sep_event);
653 int_error = IRQ_NONE;
657 end_function_with_error:
658 /* clear the interrupt */
659 sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
666 This function prepares only input DMA table for synhronic symmetric
669 int sep_prepare_input_dma_table(unsigned long app_virt_addr, unsigned long data_size, unsigned long block_size, unsigned long *lli_table_ptr, unsigned long *num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress)
671 /* pointer to the info entry of the table - the last entry */
672 struct sep_lli_entry_t *info_entry_ptr;
673 /* array of pointers ot page */
674 struct sep_lli_entry_t *lli_array_ptr;
675 /* points to the first entry to be processed in the lli_in_array */
676 unsigned long current_entry;
677 /* num entries in the virtual buffer */
678 unsigned long sep_lli_entries;
679 /* lli table pointer */
680 struct sep_lli_entry_t *in_lli_table_ptr;
681 /* the total data in one table */
682 unsigned long table_data_size;
683 /* number of entries in lli table */
684 unsigned long num_entries_in_table;
685 /* next table address */
686 unsigned long lli_table_alloc_addr;
687 unsigned long result;
689 dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
691 edbg("SEP Driver:data_size is %lu\n", data_size);
692 edbg("SEP Driver:block_size is %lu\n", block_size);
694 /* initialize the pages pointers */
695 sep_dev->in_page_array = 0;
696 sep_dev->in_num_pages = 0;
698 if (data_size == 0) {
699 /* special case - created 2 entries table with zero data */
700 in_lli_table_ptr = (struct sep_lli_entry_t *) (sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
701 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
702 in_lli_table_ptr->block_size = 0;
705 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
706 in_lli_table_ptr->block_size = 0;
708 *lli_table_ptr = sep_dev->phys_shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
709 *num_entries_ptr = 2;
710 *table_data_size_ptr = 0;
715 /* check if the pages are in Kernel Virtual Address layout */
716 if (isKernelVirtualAddress == true)
717 /* lock the pages of the kernel buffer and translate them to pages */
718 result = sep_lock_kernel_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
720 /* lock the pages of the user buffer and translate them to pages */
721 result = sep_lock_user_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
726 edbg("SEP Driver:output sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
730 sep_lli_entries = sep_dev->in_num_pages;
732 /* initiate to point after the message area */
733 lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
735 /* loop till all the entries in in array are not processed */
736 while (current_entry < sep_lli_entries) {
737 /* set the new input and output tables */
738 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
740 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
742 /* calculate the maximum size of data for input table */
743 table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry));
745 /* now calculate the table size so that it will be module block size */
746 table_data_size = (table_data_size / block_size) * block_size;
748 edbg("SEP Driver:output table_data_size is %lu\n", table_data_size);
750 /* construct input lli table */
751 sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, ¤t_entry, &num_entries_in_table, table_data_size);
753 if (info_entry_ptr == 0) {
754 /* set the output parameters to physical addresses */
755 *lli_table_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
756 *num_entries_ptr = num_entries_in_table;
757 *table_data_size_ptr = table_data_size;
759 edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr);
761 /* update the info entry of the previous in table */
762 info_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
763 info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
766 /* save the pointer to the info entry of the current tables */
767 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
770 /* print input tables */
771 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
772 sep_shared_area_phys_to_virt(*lli_table_ptr), *num_entries_ptr, *table_data_size_ptr);
774 /* the array of the pages */
775 kfree(lli_array_ptr);
777 dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
783 This function builds input and output DMA tables for synhronic
784 symmetric operations (AES, DES). It also checks that each table
785 is of the modular block size
787 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
788 unsigned long app_virt_out_addr,
789 unsigned long data_size,
790 unsigned long block_size,
791 unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress)
793 /* array of pointers of page */
794 struct sep_lli_entry_t *lli_in_array;
795 /* array of pointers of page */
796 struct sep_lli_entry_t *lli_out_array;
799 dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
801 /* initialize the pages pointers */
802 sep_dev->in_page_array = 0;
803 sep_dev->out_page_array = 0;
805 /* check if the pages are in Kernel Virtual Address layout */
806 if (isKernelVirtualAddress == true) {
807 /* lock the pages of the kernel buffer and translate them to pages */
808 result = sep_lock_kernel_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
810 edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
814 /* lock the pages of the user buffer and translate them to pages */
815 result = sep_lock_user_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
817 edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
822 if (isKernelVirtualAddress == true) {
823 result = sep_lock_kernel_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
825 edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
826 goto end_function_with_error1;
829 result = sep_lock_user_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
831 edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
832 goto end_function_with_error1;
835 edbg("sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
836 edbg("sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
837 edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
840 /* call the fucntion that creates table from the lli arrays */
841 result = sep_construct_dma_tables_from_lli(lli_in_array, sep_dev->in_num_pages, lli_out_array, sep_dev->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);
843 edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n");
844 goto end_function_with_error2;
847 /* fall through - free the lli entry arrays */
848 dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr);
849 dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr);
850 dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr);
851 end_function_with_error2:
852 kfree(lli_out_array);
853 end_function_with_error1:
856 dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result);
863 This function creates the input and output dma tables for
864 symmetric operations (AES/DES) according to the block size from LLI arays
866 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
867 unsigned long sep_in_lli_entries,
868 struct sep_lli_entry_t *lli_out_array,
869 unsigned long sep_out_lli_entries,
870 unsigned long block_size, unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr)
872 /* points to the area where next lli table can be allocated */
873 unsigned long lli_table_alloc_addr;
874 /* input lli table */
875 struct sep_lli_entry_t *in_lli_table_ptr;
876 /* output lli table */
877 struct sep_lli_entry_t *out_lli_table_ptr;
878 /* pointer to the info entry of the table - the last entry */
879 struct sep_lli_entry_t *info_in_entry_ptr;
880 /* pointer to the info entry of the table - the last entry */
881 struct sep_lli_entry_t *info_out_entry_ptr;
882 /* points to the first entry to be processed in the lli_in_array */
883 unsigned long current_in_entry;
884 /* points to the first entry to be processed in the lli_out_array */
885 unsigned long current_out_entry;
886 /* max size of the input table */
887 unsigned long in_table_data_size;
888 /* max size of the output table */
889 unsigned long out_table_data_size;
890 /* flag te signifies if this is the first tables build from the arrays */
891 unsigned long first_table_flag;
892 /* the data size that should be in table */
893 unsigned long table_data_size;
894 /* number of etnries in the input table */
895 unsigned long num_entries_in_table;
896 /* number of etnries in the output table */
897 unsigned long num_entries_out_table;
899 dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
901 /* initiate to pint after the message area */
902 lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
904 current_in_entry = 0;
905 current_out_entry = 0;
906 first_table_flag = 1;
907 info_in_entry_ptr = 0;
908 info_out_entry_ptr = 0;
910 /* loop till all the entries in in array are not processed */
911 while (current_in_entry < sep_in_lli_entries) {
912 /* set the new input and output tables */
913 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
915 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
917 /* set the first output tables */
918 out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
920 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
922 /* calculate the maximum size of data for input table */
923 in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry));
925 /* calculate the maximum size of data for output table */
926 out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry));
928 edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
929 edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
931 /* check where the data is smallest */
932 table_data_size = in_table_data_size;
933 if (table_data_size > out_table_data_size)
934 table_data_size = out_table_data_size;
936 /* now calculate the table size so that it will be module block size */
937 table_data_size = (table_data_size / block_size) * block_size;
939 dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
941 /* construct input lli table */
942 sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, ¤t_in_entry, &num_entries_in_table, table_data_size);
944 /* construct output lli table */
945 sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, ¤t_out_entry, &num_entries_out_table, table_data_size);
947 /* if info entry is null - this is the first table built */
948 if (info_in_entry_ptr == 0) {
949 /* set the output parameters to physical addresses */
950 *lli_table_in_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
951 *in_num_entries_ptr = num_entries_in_table;
952 *lli_table_out_ptr = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
953 *out_num_entries_ptr = num_entries_out_table;
954 *table_data_size_ptr = table_data_size;
956 edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
957 edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
959 /* update the info entry of the previous in table */
960 info_in_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
961 info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
963 /* update the info entry of the previous in table */
964 info_out_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
965 info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size);
968 /* save the pointer to the info entry of the current tables */
969 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
970 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
972 edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table);
973 edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr);
974 edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr);
977 /* print input tables */
978 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
979 sep_shared_area_phys_to_virt(*lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr);
980 /* print output tables */
981 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
982 sep_shared_area_phys_to_virt(*lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr);
983 dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
988 this function calculates the size of data that can be inserted into the lli
989 table from this array the condition is that either the table is full
990 (all etnries are entered), or there are no more entries in the lli array
992 unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries)
994 unsigned long table_data_size = 0;
995 unsigned long counter;
997 /* calculate the data in the out lli table if till we fill the whole
998 table or till the data has ended */
999 for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++)
1000 table_data_size += lli_in_array_ptr[counter].block_size;
1001 return table_data_size;
1005 this functions builds ont lli table from the lli_array according to
1006 the given size of data
1008 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr, struct sep_lli_entry_t *lli_table_ptr, unsigned long *num_processed_entries_ptr, unsigned long *num_table_entries_ptr, unsigned long table_data_size)
1010 unsigned long curr_table_data_size;
1011 /* counter of lli array entry */
1012 unsigned long array_counter;
1014 dbg("SEP Driver:--------> sep_build_lli_table start\n");
1016 /* init currrent table data size and lli array entry counter */
1017 curr_table_data_size = 0;
1019 *num_table_entries_ptr = 1;
1021 edbg("SEP Driver:table_data_size is %lu\n", table_data_size);
1023 /* fill the table till table size reaches the needed amount */
1024 while (curr_table_data_size < table_data_size) {
1025 /* update the number of entries in table */
1026 (*num_table_entries_ptr)++;
1028 lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address;
1029 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1030 curr_table_data_size += lli_table_ptr->block_size;
1032 edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1033 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1034 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1036 /* check for overflow of the table data */
1037 if (curr_table_data_size > table_data_size) {
1038 edbg("SEP Driver:curr_table_data_size > table_data_size\n");
1040 /* update the size of block in the table */
1041 lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1043 /* update the physical address in the lli array */
1044 lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size;
1046 /* update the block size left in the lli array */
1047 lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size);
1049 /* advance to the next entry in the lli_array */
1052 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1053 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1055 /* move to the next entry in table */
1059 /* set the info entry to default */
1060 lli_table_ptr->physical_address = 0xffffffff;
1061 lli_table_ptr->block_size = 0;
1063 edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1064 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1065 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1067 /* set the output parameter */
1068 *num_processed_entries_ptr += array_counter;
1070 edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr);
1071 dbg("SEP Driver:<-------- sep_build_lli_table end\n");
1076 this function goes over the list of the print created tables and
1079 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size)
1081 unsigned long table_count;
1082 unsigned long entries_count;
1084 dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
1087 while ((unsigned long) lli_table_ptr != 0xffffffff) {
1088 edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size);
1089 edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries);
1091 /* print entries of the table (without info entry) */
1092 for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) {
1093 edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr);
1094 edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size);
1097 /* point to the info entry */
1100 edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1101 edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1104 table_data_size = lli_table_ptr->block_size & 0xffffff;
1105 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1106 lli_table_ptr = (struct sep_lli_entry_t *)
1107 (lli_table_ptr->physical_address);
1109 edbg("SEP Driver:phys table_data_size is %lu num_table_entries is %lu lli_table_ptr is%lu\n", table_data_size, num_table_entries, (unsigned long) lli_table_ptr);
1111 if ((unsigned long) lli_table_ptr != 0xffffffff)
1112 lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_area_phys_to_virt((unsigned long) lli_table_ptr);
1116 dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1121 This function locks all the physical pages of the application virtual buffer
1122 and construct a basic lli array, where each entry holds the physical page
1123 address and the size that application data holds in this physical pages
1125 int sep_lock_user_pages(unsigned long app_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr)
1128 /* the the page of the end address of the user space buffer */
1129 unsigned long end_page;
1130 /* the page of the start address of the user space buffer */
1131 unsigned long start_page;
1132 /* the range in pages */
1133 unsigned long num_pages;
1134 struct page **page_array;
1135 struct sep_lli_entry_t *lli_array;
1136 unsigned long count;
1139 dbg("SEP Driver:--------> sep_lock_user_pages start\n");
1141 /* set start and end pages and num pages */
1142 end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1143 start_page = app_virt_addr >> PAGE_SHIFT;
1144 num_pages = end_page - start_page + 1;
1146 edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr);
1147 edbg("SEP Driver: data_size is %lu\n", data_size);
1148 edbg("SEP Driver: start_page is %lu\n", start_page);
1149 edbg("SEP Driver: end_page is %lu\n", end_page);
1150 edbg("SEP Driver: num_pages is %lu\n", num_pages);
1152 /* allocate array of pages structure pointers */
1153 page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1155 edbg("SEP Driver: kmalloc for page_array failed\n");
1161 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1163 edbg("SEP Driver: kmalloc for lli_array failed\n");
1166 goto end_function_with_error1;
1169 /* convert the application virtual address into a set of physical */
1170 down_read(¤t->mm->mmap_sem);
1171 result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0);
1172 up_read(¤t->mm->mmap_sem);
1174 /* check the number of pages locked - if not all then exit with error */
1175 if (result != num_pages) {
1176 dbg("SEP Driver: not all pages locked by get_user_pages\n");
1179 goto end_function_with_error2;
1182 /* flush the cache */
1183 for (count = 0; count < num_pages; count++)
1184 flush_dcache_page(page_array[count]);
1186 /* set the start address of the first page - app data may start not at
1187 the beginning of the page */
1188 lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK));
1190 /* check that not all the data is in the first page only */
1191 if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1192 lli_array[0].block_size = data_size;
1194 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1197 dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size);
1199 /* go from the second page to the prev before last */
1200 for (count = 1; count < (num_pages - 1); count++) {
1201 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
1202 lli_array[count].block_size = PAGE_SIZE;
1204 edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1207 /* if more then 1 pages locked - then update for the last page size needed */
1208 if (num_pages > 1) {
1209 /* update the address of the last page */
1210 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
1212 /* set the size of the last page */
1213 lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK);
1215 if (lli_array[count].block_size == 0) {
1216 dbg("app_virt_addr is %08lx\n", app_virt_addr);
1217 dbg("data_size is %lu\n", data_size);
1220 edbg("lli_array[%lu].physical_address is %08lx, \
1221 lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1224 /* set output params */
1225 *lli_array_ptr = lli_array;
1226 *num_pages_ptr = num_pages;
1227 *page_array_ptr = page_array;
1230 end_function_with_error2:
1231 /* release the cache */
1232 for (count = 0; count < num_pages; count++)
1233 page_cache_release(page_array[count]);
1235 end_function_with_error1:
1238 dbg("SEP Driver:<-------- sep_lock_user_pages end\n");
1243 This function locks all the physical pages of the kernel virtual buffer
1244 and construct a basic lli array, where each entry holds the physical
1245 page address and the size that application data holds in this physical pages
1247 int sep_lock_kernel_pages(unsigned long kernel_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr)
1250 /* the the page of the end address of the user space buffer */
1251 unsigned long end_page;
1252 /* the page of the start address of the user space buffer */
1253 unsigned long start_page;
1254 /* the range in pages */
1255 unsigned long num_pages;
1256 struct sep_lli_entry_t *lli_array;
1257 /* next kernel address to map */
1258 unsigned long next_kernel_address;
1259 unsigned long count;
1261 dbg("SEP Driver:--------> sep_lock_kernel_pages start\n");
1263 /* set start and end pages and num pages */
1264 end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
1265 start_page = kernel_virt_addr >> PAGE_SHIFT;
1266 num_pages = end_page - start_page + 1;
1268 edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr);
1269 edbg("SEP Driver: data_size is %lu\n", data_size);
1270 edbg("SEP Driver: start_page is %lx\n", start_page);
1271 edbg("SEP Driver: end_page is %lx\n", end_page);
1272 edbg("SEP Driver: num_pages is %lu\n", num_pages);
1274 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1276 edbg("SEP Driver: kmalloc for lli_array failed\n");
1281 /* set the start address of the first page - app data may start not at
1282 the beginning of the page */
1283 lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr);
1285 /* check that not all the data is in the first page only */
1286 if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
1287 lli_array[0].block_size = data_size;
1289 lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
1292 dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size);
1294 /* advance the address to the start of the next page */
1295 next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
1297 /* go from the second page to the prev before last */
1298 for (count = 1; count < (num_pages - 1); count++) {
1299 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
1300 lli_array[count].block_size = PAGE_SIZE;
1302 edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1303 next_kernel_address += PAGE_SIZE;
1306 /* if more then 1 pages locked - then update for the last page size needed */
1307 if (num_pages > 1) {
1308 /* update the address of the last page */
1309 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
1311 /* set the size of the last page */
1312 lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK);
1314 if (lli_array[count].block_size == 0) {
1315 dbg("app_virt_addr is %08lx\n", kernel_virt_addr);
1316 dbg("data_size is %lu\n", data_size);
1320 edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1322 /* set output params */
1323 *lli_array_ptr = lli_array;
1324 *num_pages_ptr = num_pages;
1325 *page_array_ptr = 0;
1327 dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n");
1332 This function releases all the application virtual buffer physical pages,
1333 that were previously locked
1335 int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag)
1337 unsigned long count;
1340 for (count = 0; count < num_pages; count++) {
1341 /* the out array was written, therefore the data was changed */
1342 if (!PageReserved(page_array_ptr[count]))
1343 SetPageDirty(page_array_ptr[count]);
1344 page_cache_release(page_array_ptr[count]);
1347 /* free in pages - the data was only read, therefore no update was done
1349 for (count = 0; count < num_pages; count++)
1350 page_cache_release(page_array_ptr[count]);
1354 /* free the array */
1355 kfree(page_array_ptr);
1361 This function raises interrupt to SEP that signals that is has a new
1364 static void sep_send_command_handler()
1366 unsigned long count;
1368 dbg("SEP Driver:--------> sep_send_command_handler start\n");
1374 for (count = 0; count < 12 * 4; count += 4)
1375 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
1377 /* update counter */
1378 sep_dev->host_to_sep_send_counter++;
1379 /* send interrupt to SEP */
1380 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
1381 dbg("SEP Driver:<-------- sep_send_command_handler end\n");
1386 This function raises interrupt to SEPm that signals that is has a
1387 new command from HOST
1389 static void sep_send_reply_command_handler()
1391 unsigned long count;
1393 dbg("SEP Driver:--------> sep_send_reply_command_handler start\n");
1397 for (count = 0; count < 12 * 4; count += 4)
1398 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
1399 /* update counter */
1400 sep_dev->host_to_sep_send_counter++;
1401 /* send the interrupt to SEP */
1402 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep_dev->host_to_sep_send_counter);
1403 /* update both counters */
1404 sep_dev->host_to_sep_send_counter++;
1405 sep_dev->sep_to_host_reply_counter++;
1406 dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n");
1412 This function handles the allocate data pool memory request
1413 This function returns calculates the physical address of the
1414 allocated memory, and the offset of this area from the mapped address.
1415 Therefore, the FVOs in user space can calculate the exact virtual
1416 address of this allocated memory
1418 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
1421 struct sep_driver_alloc_t command_args;
1423 dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
1425 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
1429 /* allocate memory */
1430 if ((sep_dev->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
1435 /* set the virtual and physical address */
1436 command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
1437 command_args.phys_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
1439 /* write the memory back to the user space */
1440 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
1444 /* set the allocation */
1445 sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
1448 dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
1453 This function handles write into allocated data pool command
1455 static int sep_write_into_data_pool_handler(unsigned long arg)
1458 unsigned long virt_address;
1459 unsigned long app_in_address;
1460 unsigned long num_bytes;
1461 unsigned long data_pool_area_addr;
1463 dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n");
1465 /* get the application address */
1466 error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address));
1470 /* get the virtual kernel address address */
1471 error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
1475 /* get the number of bytes */
1476 error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
1480 /* calculate the start of the data pool */
1481 data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
1484 /* check that the range of the virtual kernel address is correct */
1485 if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
1489 /* copy the application data */
1490 error = copy_from_user((void *) virt_address, (void *) app_in_address, num_bytes);
1492 dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
1497 this function handles the read from data pool command
1499 static int sep_read_from_data_pool_handler(unsigned long arg)
1502 /* virtual address of dest application buffer */
1503 unsigned long app_out_address;
1504 /* virtual address of the data pool */
1505 unsigned long virt_address;
1506 unsigned long num_bytes;
1507 unsigned long data_pool_area_addr;
1509 dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n");
1511 /* get the application address */
1512 error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address));
1516 /* get the virtual kernel address address */
1517 error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
1521 /* get the number of bytes */
1522 error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
1526 /* calculate the start of the data pool */
1527 data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
1529 /* check that the range of the virtual kernel address is correct */
1530 if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
1535 /* copy the application data */
1536 error = copy_to_user((void *) app_out_address, (void *) virt_address, num_bytes);
1538 dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
1544 this function handles tha request for creation of the DMA table
1545 for the synchronic symmetric operations (AES,DES)
1547 static int sep_create_sync_dma_tables_handler(unsigned long arg)
1550 /* command arguments */
1551 struct sep_driver_build_sync_table_t command_args;
1553 dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
1555 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
1559 edbg("app_in_address is %08lx\n", command_args.app_in_address);
1560 edbg("app_out_address is %08lx\n", command_args.app_out_address);
1561 edbg("data_size is %lu\n", command_args.data_in_size);
1562 edbg("block_size is %lu\n", command_args.block_size);
1564 /* check if we need to build only input table or input/output */
1565 if (command_args.app_out_address)
1566 /* prepare input and output tables */
1567 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
1568 command_args.app_out_address,
1569 command_args.data_in_size,
1570 command_args.block_size,
1571 &command_args.in_table_address,
1572 &command_args.out_table_address, &command_args.in_table_num_entries, &command_args.out_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress);
1574 /* prepare input tables */
1575 error = sep_prepare_input_dma_table(command_args.app_in_address,
1576 command_args.data_in_size, command_args.block_size, &command_args.in_table_address, &command_args.in_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress);
1581 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t));
1583 dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
1588 this function handles the request for freeing dma table for synhronic actions
1590 int sep_free_dma_table_data_handler()
1592 dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
1594 /* free input pages array */
1595 sep_free_dma_pages(sep_dev->in_page_array, sep_dev->in_num_pages, 0);
1597 /* free output pages array if needed */
1598 if (sep_dev->out_page_array)
1599 sep_free_dma_pages(sep_dev->out_page_array, sep_dev->out_num_pages, 1);
1601 /* reset all the values */
1602 sep_dev->in_page_array = 0;
1603 sep_dev->out_page_array = 0;
1604 sep_dev->in_num_pages = 0;
1605 sep_dev->out_num_pages = 0;
1606 dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
1611 this function handles the request to create the DMA tables for flow
1613 static int sep_create_flow_dma_tables_handler(unsigned long arg)
1616 struct sep_driver_build_flow_table_t command_args;
1617 /* first table - output */
1618 struct sep_lli_entry_t first_table_data;
1619 /* dma table data */
1620 struct sep_lli_entry_t last_table_data;
1621 /* pointer to the info entry of the previuos DMA table */
1622 struct sep_lli_entry_t *prev_info_entry_ptr;
1623 /* pointer to the flow data strucutre */
1624 struct sep_flow_context_t *flow_context_ptr;
1626 dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
1628 /* init variables */
1629 prev_info_entry_ptr = 0;
1630 first_table_data.physical_address = 0xffffffff;
1632 /* find the free structure for flow data */
1633 error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
1637 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
1641 /* create flow tables */
1642 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
1644 goto end_function_with_error;
1646 /* check if flow is static */
1647 if (!command_args.flow_type)
1648 /* point the info entry of the last to the info entry of the first */
1649 last_table_data = first_table_data;
1651 /* set output params */
1652 command_args.first_table_addr = first_table_data.physical_address;
1653 command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1654 command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1656 /* send the parameters to user application */
1657 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
1659 goto end_function_with_error;
1661 /* all the flow created - update the flow entry with temp id */
1662 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
1664 /* set the processing tables data in the context */
1665 if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
1666 flow_context_ptr->input_tables_in_process = first_table_data;
1668 flow_context_ptr->output_tables_in_process = first_table_data;
1672 end_function_with_error:
1673 /* free the allocated tables */
1674 sep_deallocated_flow_tables(&first_table_data);
1676 dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
1681 this functio n handles add tables to flow
1683 static int sep_add_flow_tables_handler(unsigned long arg)
1686 unsigned long num_entries;
1687 struct sep_driver_add_flow_table_t command_args;
1688 struct sep_flow_context_t *flow_context_ptr;
1689 /* first dma table data */
1690 struct sep_lli_entry_t first_table_data;
1691 /* last dma table data */
1692 struct sep_lli_entry_t last_table_data;
1693 /* pointer to the info entry of the current DMA table */
1694 struct sep_lli_entry_t *info_entry_ptr;
1696 dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n");
1698 /* get input parameters */
1699 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
1703 /* find the flow structure for the flow id */
1704 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1708 /* prepare the flow dma tables */
1709 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
1711 goto end_function_with_error;
1713 /* now check if there is already an existing add table for this flow */
1714 if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
1715 /* this buffer was for input buffers */
1716 if (flow_context_ptr->input_tables_flag) {
1717 /* add table already exists - add the new tables to the end
1719 num_entries = (flow_context_ptr->last_input_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1721 info_entry_ptr = (struct sep_lli_entry_t *)
1722 (flow_context_ptr->last_input_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1724 /* connect to list of tables */
1725 *info_entry_ptr = first_table_data;
1727 /* set the first table data */
1728 first_table_data = flow_context_ptr->first_input_table;
1730 /* set the input flag */
1731 flow_context_ptr->input_tables_flag = 1;
1733 /* set the first table data */
1734 flow_context_ptr->first_input_table = first_table_data;
1736 /* set the last table data */
1737 flow_context_ptr->last_input_table = last_table_data;
1738 } else { /* this is output tables */
1740 /* this buffer was for input buffers */
1741 if (flow_context_ptr->output_tables_flag) {
1742 /* add table already exists - add the new tables to
1743 the end of the previous */
1744 num_entries = (flow_context_ptr->last_output_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1746 info_entry_ptr = (struct sep_lli_entry_t *)
1747 (flow_context_ptr->last_output_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1749 /* connect to list of tables */
1750 *info_entry_ptr = first_table_data;
1752 /* set the first table data */
1753 first_table_data = flow_context_ptr->first_output_table;
1755 /* set the input flag */
1756 flow_context_ptr->output_tables_flag = 1;
1758 /* set the first table data */
1759 flow_context_ptr->first_output_table = first_table_data;
1761 /* set the last table data */
1762 flow_context_ptr->last_output_table = last_table_data;
1765 /* set output params */
1766 command_args.first_table_addr = first_table_data.physical_address;
1767 command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1768 command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1770 /* send the parameters to user application */
1771 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
1772 end_function_with_error:
1773 /* free the allocated tables */
1774 sep_deallocated_flow_tables(&first_table_data);
1776 dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
1781 this function add the flow add message to the specific flow
1783 static int sep_add_flow_tables_message_handler(unsigned long arg)
1786 struct sep_driver_add_message_t command_args;
1787 struct sep_flow_context_t *flow_context_ptr;
1789 dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
1791 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
1796 if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
1801 /* find the flow context */
1802 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1806 /* copy the message into context */
1807 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
1808 error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
1810 dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
1816 this function returns the physical and virtual addresses of the static pool
1818 static int sep_get_static_pool_addr_handler(unsigned long arg)
1821 struct sep_driver_static_pool_addr_t command_args;
1823 dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
1825 /*prepare the output parameters in the struct */
1826 command_args.physical_static_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
1827 command_args.virtual_static_address = sep_dev->shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
1829 edbg("SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
1831 /* send the parameters to user application */
1832 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
1833 dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
1838 this address gets the offset of the physical address from the start
1841 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
1844 struct sep_driver_get_mapped_offset_t command_args;
1846 dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
1848 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
1852 if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
1857 /*prepare the output parameters in the struct */
1858 command_args.offset = command_args.physical_address - sep_dev->phys_shared_area_addr;
1860 edbg("SEP Driver:physical_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
1862 /* send the parameters to user application */
1863 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
1865 dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
1873 static int sep_start_handler(void)
1875 unsigned long reg_val;
1876 unsigned long error = 0;
1878 dbg("SEP Driver:--------> sep_start_handler start\n");
1880 /* wait in polling for message from SEP */
1882 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
1885 /* check the value */
1887 /* fatal error - read erro status from GPRO */
1888 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
1890 dbg("SEP Driver:<-------- sep_start_handler end\n");
1895 this function handles the request for SEP initialization
1897 static int sep_init_handler(unsigned long arg)
1899 unsigned long message_word;
1900 unsigned long *message_ptr;
1901 struct sep_driver_init_t command_args;
1902 unsigned long counter;
1903 unsigned long error;
1904 unsigned long reg_val;
1906 dbg("SEP Driver:--------> sep_init_handler start\n");
1909 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
1911 dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
1916 /* PATCH - configure the DMA to single -burst instead of multi-burst */
1917 /*sep_configure_dma_burst(); */
1919 dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
1921 message_ptr = (unsigned long *) command_args.message_addr;
1923 /* set the base address of the SRAM */
1924 sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
1926 for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) {
1927 get_user(message_word, message_ptr);
1928 /* write data to SRAM */
1929 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR, message_word);
1930 edbg("SEP Driver:message_word is %lu\n", message_word);
1931 /* wait for write complete */
1932 sep_wait_sram_write(sep_dev);
1934 dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
1936 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
1939 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
1940 while (!(reg_val & 0xFFFFFFFD));
1942 dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
1944 /* check the value */
1945 if (reg_val == 0x1) {
1946 edbg("SEP Driver:init failed\n");
1948 error = sep_read_reg(sep_dev, 0x8060);
1949 edbg("SEP Driver:sw monitor is %lu\n", error);
1951 /* fatal error - read erro status from GPRO */
1952 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
1953 edbg("SEP Driver:error is %lu\n", error);
1956 dbg("SEP Driver:<-------- sep_init_handler end\n");
1962 this function handles the request cache and resident reallocation
1964 static int sep_realloc_cache_resident_handler(unsigned long arg)
1967 unsigned long phys_cache_address;
1968 unsigned long phys_resident_address;
1969 struct sep_driver_realloc_cache_resident_t command_args;
1972 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_realloc_cache_resident_t));
1976 /* copy cache and resident to the their intended locations */
1977 error = sep_copy_cache_resident_to_area(command_args.cache_addr, command_args.cache_size_in_bytes, command_args.resident_addr, command_args.resident_size_in_bytes, &phys_cache_address, &phys_resident_address);
1981 /* lock the area (if needed) */
1982 sep_lock_cache_resident_area();
1984 command_args.new_base_addr = sep_dev->phys_shared_area_addr;
1986 /* find the new base address according to the lowest address between
1987 cache, resident and shared area */
1988 if (phys_resident_address < command_args.new_base_addr)
1989 command_args.new_base_addr = phys_resident_address;
1990 if (phys_cache_address < command_args.new_base_addr)
1991 command_args.new_base_addr = phys_cache_address;
1993 /* set the return parameters */
1994 command_args.new_cache_addr = phys_cache_address;
1995 command_args.new_resident_addr = phys_resident_address;
1997 /* set the new shared area */
1998 command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
2000 edbg("SEP Driver:command_args.new_shared_area_addr is %08lx\n", command_args.new_shared_area_addr);
2001 edbg("SEP Driver:command_args.new_base_addr is %08lx\n", command_args.new_base_addr);
2002 edbg("SEP Driver:command_args.new_resident_addr is %08lx\n", command_args.new_resident_addr);
2003 edbg("SEP Driver:command_args.new_cache_addr is %08lx\n", command_args.new_cache_addr);
2005 /* return to user */
2006 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_realloc_cache_resident_t));
2012 this function handles the request for get time
2014 static int sep_get_time_handler(unsigned long arg)
2017 struct sep_driver_get_time_t command_args;
2019 error = sep_set_time(&command_args.time_physical_address, &command_args.time_value);
2020 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_get_time_t));
2026 This api handles the setting of API mode to blocking or non-blocking
2028 static int sep_set_api_mode_handler(unsigned long arg)
2031 unsigned long mode_flag;
2033 dbg("SEP Driver:--------> sep_set_api_mode_handler start\n");
2035 error = get_user(mode_flag, &(((struct sep_driver_set_api_mode_t *) arg)->mode));
2039 /* set the global flag */
2040 sep_dev->block_mode_flag = mode_flag;
2042 dbg("SEP Driver:<-------- sep_set_api_mode_handler end\n");
2047 This API handles the end transaction request
2049 static int sep_end_transaction_handler(unsigned long arg)
2051 dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
2053 #if 0 /*!SEP_DRIVER_POLLING_MODE */
2055 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
2057 /* release IRQ line */
2058 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
2060 /* lock the sep mutex */
2061 mutex_unlock(&sep_mutex);
2064 dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
2069 /* handler for flow done interrupt */
2070 static void sep_flow_done_handler(struct work_struct *work)
2072 struct sep_flow_context_t *flow_data_ptr;
2074 /* obtain the mutex */
2075 mutex_lock(&sep_mutex);
2077 /* get the pointer to context */
2078 flow_data_ptr = (struct sep_flow_context_t *) work;
2080 /* free all the current input tables in sep */
2081 sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
2083 /* free all the current tables output tables in SEP (if needed) */
2084 if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
2085 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
2087 /* check if we have additional tables to be sent to SEP only input
2088 flag may be checked */
2089 if (flow_data_ptr->input_tables_flag) {
2090 /* copy the message to the shared RAM and signal SEP */
2091 memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes);
2093 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
2095 mutex_unlock(&sep_mutex);
2100 This function creates a list of tables for flow and returns the data for
2101 the first and last tables of the list
2103 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
2104 unsigned long first_buff_addr, struct sep_flow_context_t *flow_data_ptr, struct sep_lli_entry_t *first_table_data_ptr, struct sep_lli_entry_t *last_table_data_ptr, bool isKernelVirtualAddress)
2107 unsigned long virt_buff_addr;
2108 unsigned long virt_buff_size;
2109 struct sep_lli_entry_t table_data;
2110 struct sep_lli_entry_t *info_entry_ptr;
2111 struct sep_lli_entry_t *prev_info_entry_ptr;
2116 prev_info_entry_ptr = 0;
2118 /* init the first table to default */
2119 table_data.physical_address = 0xffffffff;
2120 first_table_data_ptr->physical_address = 0xffffffff;
2121 table_data.block_size = 0;
2123 for (i = 0; i < num_virtual_buffers; i++) {
2124 /* get the virtual buffer address */
2125 error = get_user(virt_buff_addr, &first_buff_addr);
2129 /* get the virtual buffer size */
2131 error = get_user(virt_buff_size, &first_buff_addr);
2135 /* advance the address to point to the next pair of address|size */
2138 /* now prepare the one flow LLI table from the data */
2139 error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress);
2144 /* if this is the first table - save it to return to the user
2146 *first_table_data_ptr = table_data;
2148 /* set the pointer to info entry */
2149 prev_info_entry_ptr = info_entry_ptr;
2151 /* not first table - the previous table info entry should
2153 prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size);
2155 /* set the pointer to info entry */
2156 prev_info_entry_ptr = info_entry_ptr;
2160 /* set the last table data */
2161 *last_table_data_ptr = table_data;
2168 This function creates one DMA table for flow and returns its data,
2169 and pointer to its info entry
2171 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr, unsigned long virt_buff_size, struct sep_lli_entry_t *table_data, struct sep_lli_entry_t **info_entry_ptr, struct sep_flow_context_t *flow_data_ptr, bool isKernelVirtualAddress)
2174 /* the range in pages */
2175 unsigned long lli_array_size;
2176 struct sep_lli_entry_t *lli_array;
2177 struct sep_lli_entry_t *flow_dma_table_entry_ptr;
2178 unsigned long *start_dma_table_ptr;
2179 /* total table data counter */
2180 unsigned long dma_table_data_count;
2181 /* pointer that will keep the pointer to the pages of the virtual buffer */
2182 struct page **page_array_ptr;
2183 unsigned long entry_count;
2185 /* find the space for the new table */
2186 error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
2190 /* check if the pages are in Kernel Virtual Address layout */
2191 if (isKernelVirtualAddress == true)
2192 /* lock kernel buffer in the memory */
2193 error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2195 /* lock user buffer in the memory */
2196 error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2201 /* set the pointer to page array at the beginning of table - this table is
2202 now considered taken */
2203 *start_dma_table_ptr = lli_array_size;
2205 /* point to the place of the pages pointers of the table */
2206 start_dma_table_ptr++;
2208 /* set the pages pointer */
2209 *start_dma_table_ptr = (unsigned long) page_array_ptr;
2211 /* set the pointer to the first entry */
2212 flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr);
2214 /* now create the entries for table */
2215 for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) {
2216 flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address;
2218 flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size;
2220 /* set the total data of a table */
2221 dma_table_data_count += lli_array[entry_count].block_size;
2223 flow_dma_table_entry_ptr++;
2226 /* set the physical address */
2227 table_data->physical_address = virt_to_phys(start_dma_table_ptr);
2229 /* set the num_entries and total data size */
2230 table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count);
2232 /* set the info entry */
2233 flow_dma_table_entry_ptr->physical_address = 0xffffffff;
2234 flow_dma_table_entry_ptr->block_size = 0;
2236 /* set the pointer to info entry */
2237 *info_entry_ptr = flow_dma_table_entry_ptr;
2239 /* the array of the lli entries */
2247 This function returns pointer to the flow data structure
2248 that contains the given id
2250 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr)
2252 unsigned long count;
2256 always search for flow with id default first - in case we
2257 already started working on the flow there can be no situation
2258 when 2 flows are with default flag
2260 for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
2261 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
2262 *flow_data_ptr = &sep_dev->flows_data_array[count];
2267 if (count == SEP_DRIVER_NUM_FLOWS)
2275 this function find a space for the new flow dma table
2277 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr)
2280 /* pointer to the id field of the flow dma table */
2281 unsigned long *start_table_ptr;
2282 unsigned long flow_dma_area_start_addr;
2283 unsigned long flow_dma_area_end_addr;
2284 /* maximum table size in words */
2285 unsigned long table_size_in_words;
2287 /* find the start address of the flow DMA table area */
2288 flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
2290 /* set end address of the flow table area */
2291 flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
2293 /* set table size in words */
2294 table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
2296 /* set the pointer to the start address of DMA area */
2297 start_table_ptr = (unsigned long *) flow_dma_area_start_addr;
2299 /* find the space for the next table */
2300 while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr))
2301 start_table_ptr += table_size_in_words;
2303 /* check if we reached the end of floa tables area */
2304 if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr)
2307 *table_address_ptr = start_table_ptr;
2313 this function goes over all the flow tables connected to the given
2314 table and deallocate them
2316 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
2319 unsigned long *table_ptr;
2320 /* end address of the flow dma area */
2321 unsigned long num_entries;
2322 unsigned long num_pages;
2323 struct page **pages_ptr;
2324 /* maximum table size in words */
2325 struct sep_lli_entry_t *info_entry_ptr;
2327 /* set the pointer to the first table */
2328 table_ptr = (unsigned long *) first_table_ptr->physical_address;
2330 /* set the num of entries */
2331 num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
2332 & SEP_NUM_ENTRIES_MASK;
2334 /* go over all the connected tables */
2335 while (*table_ptr != 0xffffffff) {
2336 /* get number of pages */
2337 num_pages = *(table_ptr - 2);
2339 /* get the pointer to the pages */
2340 pages_ptr = (struct page **) (*(table_ptr - 1));
2342 /* free the pages */
2343 sep_free_dma_pages(pages_ptr, num_pages, 1);
2345 /* goto to the info entry */
2346 info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1);
2348 table_ptr = (unsigned long *) info_entry_ptr->physical_address;
2349 num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2356 This function handler the set flow id command
2358 static int sep_set_flow_id_handler(unsigned long arg)
2361 unsigned long flow_id;
2362 struct sep_flow_context_t *flow_data_ptr;
2364 dbg("------------>SEP Driver: sep_set_flow_id_handler start\n");
2366 error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id));
2370 /* find the flow data structure that was just used for creating new flow
2371 - its id should be default */
2372 error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
2377 flow_data_ptr->flow_id = flow_id;
2380 dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n");
2386 calculates time and sets it at the predefined address
2388 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr)
2390 struct timeval time;
2391 /* address of time in the kernel */
2392 unsigned long time_addr;
2395 dbg("SEP Driver:--------> sep_set_time start\n");
2397 do_gettimeofday(&time);
2399 /* set value in the SYSTEM MEMORY offset */
2400 time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
2402 *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN;
2403 *(unsigned long *) (time_addr + 4) = time.tv_sec;
2405 edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec);
2406 edbg("SEP Driver:time_addr is %lu\n", time_addr);
2407 edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr);
2409 /* set the output parameters if needed */
2411 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
2413 if (time_in_sec_ptr)
2414 *time_in_sec_ptr = time.tv_sec;
2416 dbg("SEP Driver:<-------- sep_set_time end\n");
2421 static void sep_wait_busy(struct sep_device *dev)
2426 reg = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
2431 PATCH for configuring the DMA to single burst instead of multi-burst
2433 static void sep_configure_dma_burst(void)
2435 #define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL
2437 dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
2439 /* request access to registers from SEP */
2440 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2442 dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n");
2444 sep_wait_busy(sep_dev);
2446 dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n");
2448 /* set the DMA burst register to single burst */
2449 sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
2451 /* release the sep busy */
2452 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
2453 sep_wait_busy(sep_dev);
2455 dbg("SEP Driver:<-------- sep_configure_dma_burst done \n");
2460 this function registers the driver to the file system
2462 static int sep_register_driver_to_fs(void)
2464 int ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
2466 edbg("sep_driver:major number allocation failed, retval is %d\n", ret_val);
2470 /* set the files operations structure */
2471 g_sep_fops.owner = THIS_MODULE;
2472 g_sep_fops.ioctl = sep_ioctl;
2473 g_sep_fops.poll = sep_poll;
2474 g_sep_fops.open = sep_open;
2475 g_sep_fops.release = sep_release;
2476 g_sep_fops.mmap = sep_mmap;
2479 cdev_init(&g_sep_cdev, &g_sep_fops);
2480 g_sep_cdev.owner = THIS_MODULE;
2482 /* register the driver with the kernel */
2483 ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
2486 edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val);
2487 goto end_function_unregister_devnum;
2492 end_function_unregister_devnum:
2494 /* unregister dev numbers */
2495 unregister_chrdev_region(g_sep_device_number, 1);
2502 this function unregisters driver from fs
2504 static void sep_unregister_driver_from_fs(void)
2506 cdev_del(&g_sep_cdev);
2507 /* unregister dev numbers */
2508 unregister_chrdev_region(g_sep_device_number, 1);
2512 /*--------------------------------------------------------------
2514 ----------------------------------------------------------------*/
2515 static int __init sep_init(void)
2519 int size; /* size of memory for allocation */
2521 dbg("SEP Driver:-------->Init start\n");
2522 edbg("sep->shared_area_addr = %lx\n", (unsigned long) &sep_dev->shared_area_addr);
2524 /* transaction counter that coordinates the transactions between SEP
2526 sep_dev->host_to_sep_send_counter = 0;
2528 /* counter for the messages from sep */
2529 sep_dev->sep_to_host_reply_counter = 0;
2531 /* counter for the number of bytes allocated in the pool
2532 for the current transaction */
2533 sep_dev->data_pool_bytes_allocated = 0;
2535 /* set the starting mode to blocking */
2536 sep_dev->block_mode_flag = 1;
2538 ret_val = sep_register_driver_to_device();
2540 edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val);
2541 goto end_function_unregister_from_fs;
2543 /* calculate the total size for allocation */
2544 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
2545 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
2547 /* allocate the shared area */
2548 if (sep_map_and_alloc_shared_area(size, &sep_dev->shared_area_addr, &sep_dev->phys_shared_area_addr)) {
2550 /* allocation failed */
2551 goto end_function_unmap_io_memory;
2553 /* now set the memory regions */
2554 sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
2556 edbg("SEP Driver: g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
2558 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
2559 /* send the new SHARED MESSAGE AREA to the SEP */
2560 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep_dev->phys_shared_area_addr);
2562 /* poll for SEP response */
2563 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
2564 while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
2565 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
2567 /* check the return value (register) */
2568 if (retVal != sep_dev->phys_shared_area_addr) {
2570 goto end_function_deallocate_message_area;
2573 /* init the flow contextes */
2574 for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
2575 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
2577 sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
2578 if (sep_dev->flow_wq_ptr == 0) {
2580 edbg("sep_driver:flow queue creation failed\n");
2581 goto end_function_deallocate_sep_shared_area;
2583 edbg("SEP Driver: create flow workqueue \n");
2585 /* register driver to fs */
2586 ret_val = sep_register_driver_to_fs();
2588 goto end_function_deallocate_sep_shared_area;
2589 /* load the rom code */
2590 sep_load_rom_code();
2592 end_function_unregister_from_fs:
2593 /* unregister from fs */
2594 sep_unregister_driver_from_fs();
2595 end_function_deallocate_sep_shared_area:
2596 /* de-allocate shared area */
2597 sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
2598 end_function_unmap_io_memory:
2599 iounmap((void *) sep_dev->reg_base_address);
2600 /* release io memory region */
2601 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
2603 dbg("SEP Driver:<-------- Init end\n");
2608 /*-------------------------------------------------------------
2610 --------------------------------------------------------------*/
2611 static void __exit sep_exit(void)
2615 dbg("SEP Driver:--------> Exit start\n");
2617 /* unregister from fs */
2618 sep_unregister_driver_from_fs();
2619 /* calculate the total size for de-allocation */
2620 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
2621 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
2622 /* free shared area */
2623 sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
2624 edbg("SEP Driver: free pages SEP SHARED AREA \n");
2625 iounmap((void *) sep_dev->reg_base_address);
2626 edbg("SEP Driver: iounmap \n");
2627 /* release io memory region */
2628 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
2629 edbg("SEP Driver: release_mem_region \n");
2630 dbg("SEP Driver:<-------- Exit end\n");
2634 module_init(sep_init);
2635 module_exit(sep_exit);
2637 MODULE_LICENSE("GPL");