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"
52 /*----------------------------------------
54 -----------------------------------------*/
57 #define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
59 /*--------------------------------------
61 -----------------------------------------*/
65 /*--------------------------------------------
67 --------------------------------------------*/
69 /* debug messages level */
70 INT_MODULE_PARM(sepDebug, 0x0);
71 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
73 /* address of the shared memory allocated during init for SEP driver */
74 static unsigned long g_sep_shared_area_addr;
76 /* the physical address of the shared area */
77 static unsigned long g_sep_phys_shared_area_addr;
79 /* Message Shared Area start address - will be allocated during init */
80 static unsigned long g_message_shared_area_addr;
82 /* major and minor device numbers */
83 static dev_t g_sep_device_number;
85 /* the files operations structure of the driver */
86 static struct file_operations g_sep_fops;
88 /* cdev struct of the driver */
89 static struct cdev g_sep_cdev;
92 mutex for the access to the internals of the sep driver
94 static DEFINE_MUTEX(sep_mutex);
97 /* wait queue head (event) of the driver */
98 DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
101 /* start address of the access to the SEP registers from driver */
102 unsigned long g_sep_reg_base_address;
104 /* transaction counter that coordinates the transactions between SEP and HOST */
105 static unsigned long sep_host_to_sep_send_counter;
107 /* counter for the messages from sep */
108 static unsigned long sep_sep_to_host_reply_counter;
110 /* counter for the number of bytes allocated in the pool for the current
112 static unsigned long sep_data_pool_bytes_allocated;
114 /* array of pointers to the pages that represent input data for the synchronic
116 struct page **sep_in_page_array;
118 /* array of pointers to the pages that represent out data for the synchronic
120 struct page **sep_out_page_array;
122 /* number of pages in the sep_in_page_array */
123 unsigned long sep_in_num_pages;
125 /* number of pages in the sep_out_page_array */
126 unsigned long sep_out_num_pages;
128 /* global data for every flow */
129 static struct sep_flow_context_t g_sep_flows_data_array[SEP_DRIVER_NUM_FLOWS];
131 /* flag for API mode - 1 -is blocking, 0 is non-blocking */
132 static unsigned long g_sep_block_mode_flag;
134 /* pointer to the workqueue that handles the flow done interrupts */
135 static struct workqueue_struct *g_sep_flow_wq_ptr;
137 /*------------------------------------------------
139 ---------------------------------------------------*/
142 interrupt handler function
144 irqreturn_t sep_inthandler(int irq, void *dev_id);
147 this function registers the driver to the file system
149 static int sep_register_driver_to_fs(void);
152 this function unregisters driver from fs
154 static void sep_unregister_driver_from_fs(void);
157 this function calculates the size of data that can be inserted into the lli
158 table from this array the condition is that either the table is full
159 (all etnries are entered), or there are no more entries in the lli array
161 static unsigned long sep_calculate_lli_table_max_size(
162 struct sep_lli_entry_t *lli_in_array_ptr,
163 unsigned long num_array_entries);
165 this functions builds ont lli table from the lli_array according to the
168 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
169 struct sep_lli_entry_t *lli_table_ptr,
170 unsigned long *num_processed_entries_ptr,
171 unsigned long *num_table_entries_ptr,
172 unsigned long table_data_size);
175 this function goes over the list of the print created tables and prints
178 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
179 unsigned long num_table_entries,
180 unsigned long table_data_size);
185 This function raises interrupt to SEPm that signals that is has a new
188 static void sep_send_command_handler(void);
192 This function raises interrupt to SEP that signals that is has a
195 static void sep_send_reply_command_handler(void);
198 This function handles the allocate data pool memory request
199 This function returns calculates the physical address of the allocated memory
200 and the offset of this area from the mapped address. Therefore, the FVOs in
201 user space can calculate the exact virtual address of this allocated memory
203 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
207 This function handles write into allocated data pool command
209 static int sep_write_into_data_pool_handler(unsigned long arg);
212 this function handles the read from data pool command
214 static int sep_read_from_data_pool_handler(unsigned long arg);
217 this function handles tha request for creation of the DMA table
218 for the synchronic symmetric operations (AES,DES)
220 static int sep_create_sync_dma_tables_handler(unsigned long arg);
223 this function handles the request to create the DMA tables for flow
225 static int sep_create_flow_dma_tables_handler(unsigned long arg);
228 This API handles the end transaction request
230 static int sep_end_transaction_handler(unsigned long arg);
234 this function handles add tables to flow
236 static int sep_add_flow_tables_handler(unsigned long arg);
239 this function add the flow add message to the specific flow
241 static int sep_add_flow_tables_message_handler(unsigned long arg);
244 this function handles the request for SEP start
246 static int sep_start_handler(void);
249 this function handles the request for SEP initialization
251 static int sep_init_handler(unsigned long arg);
254 this function handles the request cache and resident reallocation
256 static int sep_realloc_cache_resident_handler(unsigned long arg);
260 This api handles the setting of API mode to blocking or non-blocking
262 static int sep_set_api_mode_handler(unsigned long arg);
264 /* handler for flow done interrupt */
265 static void sep_flow_done_handler(struct work_struct *work);
268 This function locks all the physical pages of the kernel virtual buffer
269 and construct a basic lli array, where each entry holds the physical
270 page address and the size that application data holds in this physical pages
272 static int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
273 unsigned long data_size,
274 unsigned long *num_pages_ptr,
275 struct sep_lli_entry_t **lli_array_ptr,
276 struct page ***page_array_ptr);
279 This function creates one DMA table for flow and returns its data,
280 and pointer to its info entry
282 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr,
283 unsigned long virt_buff_size,
284 struct sep_lli_entry_t *table_data,
285 struct sep_lli_entry_t **info_entry_ptr,
286 struct sep_flow_context_t *flow_data_ptr,
287 bool isKernelVirtualAddress);
290 This function creates a list of tables for flow and returns the data for the
291 first and last tables of the list
293 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
294 unsigned long first_buff_addr,
295 struct sep_flow_context_t *flow_data_ptr,
296 struct sep_lli_entry_t *first_table_data_ptr,
297 struct sep_lli_entry_t *last_table_data_ptr,
298 bool isKernelVirtualAddress);
301 this function find a space for the new flow dma table
303 static int sep_find_free_flow_dma_table_space(
304 unsigned long **table_address_ptr);
307 this function goes over all the flow tables connected to the given table and
310 static void sep_deallocated_flow_tables(
311 struct sep_lli_entry_t *first_table_ptr);
314 This function handler the set flow id command
316 static int sep_set_flow_id_handler(unsigned long arg);
319 This function returns pointer to the flow data structure
320 that conatins the given id
322 static int sep_find_flow_context(unsigned long flow_id,
323 struct sep_flow_context_t **flow_data_ptr);
327 this function returns the physical and virtual addresses of the static pool
329 static int sep_get_static_pool_addr_handler(unsigned long arg);
332 this address gets the offset of the physical address from the start of
335 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
339 this function handles the request for get time
341 static int sep_get_time_handler(unsigned long arg);
344 calculates time and sets it at the predefined address
346 static int sep_set_time(unsigned long *address_ptr,
347 unsigned long *time_in_sec_ptr);
350 PATCH for configuring the DMA to single burst instead of multi-burst
352 static void sep_configure_dma_burst(void);
355 This function locks all the physical pages of the
356 application virtual buffer and construct a basic lli
357 array, where each entry holds the physical page address
358 and the size that application data holds in this physical pages
360 static int sep_lock_user_pages(unsigned long app_virt_addr,
361 unsigned long data_size,
362 unsigned long *num_pages_ptr,
363 struct sep_lli_entry_t **lli_array_ptr,
364 struct page ***page_array_ptr);
366 /*---------------------------------------------
368 -----------------------------------------------*/
371 this function locks SEP by locking the semaphore
375 mutex_lock(&sep_mutex);
381 this function unlocks SEP
386 mutex_unlock(&sep_mutex);
390 this function returns the address of the message shared area
392 void sep_map_shared_area(unsigned long *mappedAddr_ptr)
394 *mappedAddr_ptr = g_sep_shared_area_addr;
398 this function returns the address of the message shared area
400 void sep_send_msg_rdy_cmd()
402 sep_send_command_handler();
405 /* this functions frees all the resources that were allocated for the building
406 of the LLI DMA tables */
407 void sep_free_dma_resources()
409 sep_free_dma_table_data_handler();
412 /* poll(suspend), until reply from sep */
413 void sep_driver_poll()
415 unsigned long retVal = 0;
417 #ifdef SEP_DRIVER_POLLING_MODE
419 while (sep_host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
420 SEP_READ_REGISTER(g_sep_reg_base_address +
421 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
424 sep_sep_to_host_reply_counter++;
426 /* poll, until reply from sep */
427 wait_event(g_sep_event,
428 (sep_host_to_sep_send_counter == sep_sep_to_host_reply_counter));
433 /*----------------------------------------------------------------------
434 open function of the character driver - must only lock the mutex
435 must also release the memory data pool allocations
436 ------------------------------------------------------------------------*/
437 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
444 ---------------------*/
446 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> open start\n");
450 /* check the blocking mode */
451 if (g_sep_block_mode_flag)
453 mutex_lock(&sep_mutex);
455 error = mutex_trylock(&sep_mutex);
457 /* check the error */
459 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
460 "SEP Driver: down_interruptible failed\n");
465 /* release data pool allocations */
466 sep_data_pool_bytes_allocated = 0;
470 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- open end\n");
478 /*------------------------------------------------------------
480 -------------------------------------------------------------*/
481 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
485 ---------------------*/
487 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
488 "----------->SEP Driver: sep_release start\n");
490 #if 0/*!SEP_DRIVER_POLLING_MODE*/
492 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
494 /* release IRQ line */
495 free_irq(SEP_DIRVER_IRQ_NUM, &g_sep_reg_base_address);
499 /* unlock the sep mutex */
500 mutex_unlock(&sep_mutex);
502 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
503 "SEP Driver:<-------- sep_release end\n");
511 /*---------------------------------------------------------------
512 map function - this functions maps the message shared area
513 -----------------------------------------------------------------*/
514 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
517 unsigned long phys_addr;
519 /*-----------------------
521 -------------------------*/
523 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "-------->SEP Driver: mmap start\n");
525 /* check that the size of the mapped range is as the size of the message
527 if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
528 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
529 "SEP Driver mmap requested size is more than allowed\n");
530 printk(KERN_WARNING "SEP Driver mmap requested size is more \
532 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
534 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
539 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
540 "SEP Driver:g_message_shared_area_addr is %08lx\n",
541 g_message_shared_area_addr);
543 /* get physical address */
544 phys_addr = g_sep_phys_shared_area_addr;
546 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: phys_addr is %08lx\n",
549 if (remap_pfn_range(vma,
551 phys_addr >> PAGE_SHIFT,
552 vma->vm_end - vma->vm_start,
553 vma->vm_page_prot)) {
554 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
555 "SEP Driver remap_page_range failed\n");
556 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
560 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- mmap end\n");
566 /*-----------------------------------------------
568 *----------------------------------------------*/
569 static unsigned int sep_poll(struct file *filp, poll_table *wait)
573 unsigned int mask = 0;
576 unsigned long retVal = 0;
578 /*----------------------------------------------
580 -------------------------------------------------*/
582 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "---------->SEP Driver poll: start\n");
585 #if SEP_DRIVER_POLLING_MODE
587 while (sep_host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
588 SEP_READ_REGISTER(g_sep_reg_base_address +
589 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
592 for (count = 0; count < 10 * 4; count += 4)
593 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
594 "Poll Debug Word %lu of the message is %lu\n",
596 *((unsigned long *)(g_sep_shared_area_addr +
597 SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
600 sep_sep_to_host_reply_counter++;
602 /* add the event to the polling wait table */
603 poll_wait(filp, &g_sep_event, wait);
607 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
608 "sep_host_to_sep_send_counter is %lu\n",
609 sep_host_to_sep_send_counter);
610 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
611 "sep_sep_to_host_reply_counter is %lu\n",
612 sep_sep_to_host_reply_counter);
614 /* check if the data is ready */
615 if (sep_host_to_sep_send_counter == sep_sep_to_host_reply_counter) {
616 for (count = 0; count < 12 * 4; count += 4)
617 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
618 "Sep Mesg Word %lu of the message is %lu\n",
619 count, *((unsigned long *)(g_sep_shared_area_addr + count)));
621 for (count = 0; count < 10 * 4; count += 4)
622 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
623 "Debug Data Word %lu of the message is %lu\n",
625 *((unsigned long *)(g_sep_shared_area_addr + 0x1800 + count)));
627 SEP_READ_REGISTER(g_sep_reg_base_address +
628 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
630 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "retVal is %lu\n", retVal);
631 /* check if the this is sep reply or request */
633 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
634 "SEP Driver: sep request in\n");
636 mask |= POLLOUT | POLLWRNORM;
638 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: sep reply in\n");
639 mask |= POLLIN | POLLRDNORM;
643 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- poll exit\n");
648 static int sep_ioctl(struct inode *inode,
657 /*------------------------
659 ------------------------*/
662 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
663 "------------>SEP Driver: ioctl start\n");
665 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: cmd is %x\n", cmd);
667 /* check that the command is for sep device */
668 if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
672 case SEP_IOCSENDSEPCOMMAND:
674 /* send command to SEP */
675 sep_send_command_handler();
677 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
678 "SEP Driver: after sep_send_command_handler\n");
682 case SEP_IOCSENDSEPRPLYCOMMAND:
684 /* send reply command to SEP */
685 sep_send_reply_command_handler();
689 case SEP_IOCALLOCDATAPOLL:
691 /* allocate data pool */
692 error = sep_allocate_data_pool_memory_handler(arg);
696 case SEP_IOCWRITEDATAPOLL:
698 /* write data into memory pool */
699 error = sep_write_into_data_pool_handler(arg);
703 case SEP_IOCREADDATAPOLL:
705 /* read data from data pool into application memory */
706 error = sep_read_from_data_pool_handler(arg);
710 case SEP_IOCCREATESYMDMATABLE:
712 /* create dma table for synhronic operation */
713 error = sep_create_sync_dma_tables_handler(arg);
717 case SEP_IOCCREATEFLOWDMATABLE:
719 /* create flow dma tables */
720 error = sep_create_flow_dma_tables_handler(arg);
724 case SEP_IOCFREEDMATABLEDATA:
727 error = sep_free_dma_table_data_handler();
731 case SEP_IOCSETFLOWID:
734 error = sep_set_flow_id_handler(arg);
738 case SEP_IOCADDFLOWTABLE:
740 /* add tables to the dynamic flow */
741 error = sep_add_flow_tables_handler(arg);
745 case SEP_IOCADDFLOWMESSAGE:
747 /* add message of add tables to flow */
748 error = sep_add_flow_tables_message_handler(arg);
752 case SEP_IOCSEPSTART:
754 /* start command to sep */
755 error = sep_start_handler();
760 /* init command to sep */
761 error = sep_init_handler(arg);
764 case SEP_IOCSETAPIMODE:
766 /* set non- blocking mode */
767 error = sep_set_api_mode_handler(arg);
771 case SEP_IOCGETSTATICPOOLADDR:
773 /* get the physical and virtual addresses of the static pool */
774 error = sep_get_static_pool_addr_handler(arg);
778 case SEP_IOCENDTRANSACTION:
780 error = sep_end_transaction_handler(arg);
784 case SEP_IOCREALLOCCACHERES:
786 error = sep_realloc_cache_resident_handler(arg);
790 case SEP_IOCGETMAPPEDADDROFFSET:
792 error = sep_get_physical_mapped_offset_handler(arg);
797 error = sep_get_time_handler(arg);
806 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
807 "SEP Driver:<-------- ioctl end\n");
814 this function registers the driver to the file system
816 static int sep_register_driver_to_fs(void)
821 /*---------------------
823 -----------------------*/
825 ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
827 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
828 "sep_driver:major number allocation failed, retval is %d\n", ret_val);
832 /* set the files operations structure */
833 g_sep_fops.owner = THIS_MODULE;
834 g_sep_fops.ioctl = sep_ioctl;
835 g_sep_fops.poll = sep_poll;
836 g_sep_fops.open = sep_open;
837 g_sep_fops.release = sep_release;
838 g_sep_fops.mmap = sep_mmap;
841 cdev_init(&g_sep_cdev, &g_sep_fops);
842 g_sep_cdev.owner = THIS_MODULE;
844 /* register the driver with the kernel */
845 ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
848 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
849 "sep_driver:cdev_add failed, retval is %d\n",
851 goto end_function_unregister_devnum;
856 end_function_unregister_devnum:
858 /* unregister dev numbers */
859 unregister_chrdev_region(g_sep_device_number, 1);
867 this function unregisters driver from fs
869 static void sep_unregister_driver_from_fs(void)
871 /*-------------------
873 ---------------------*/
875 cdev_del(&g_sep_cdev);
877 /* unregister dev numbers */
878 unregister_chrdev_region(g_sep_device_number, 1);
881 /*--------------------------------------------------------------
883 ----------------------------------------------------------------*/
884 static int __init sep_init(void)
892 /* size to of memory for allocation */
895 /*------------------------
897 ------------------------*/
899 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
900 "SEP Driver:-------->Init start\n");
901 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
902 "g_sep_shared_area_addr = %lx\n",
903 (unsigned long)&g_sep_shared_area_addr);
907 /* transaction counter that coordinates the transactions between SEP
909 sep_host_to_sep_send_counter = 0;
911 /* counter for the messages from sep */
912 sep_sep_to_host_reply_counter = 0;
914 /* counter for the number of bytes allocated in the pool
915 for the current transaction */
916 sep_data_pool_bytes_allocated = 0;
918 /* set the starting mode to blocking */
919 g_sep_block_mode_flag = 1;
922 ret_val = sep_register_driver_to_device();
924 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
925 "sep_driver:sep_driver_to_device failed, ret_val is %d\n",
927 goto end_function_unregister_from_fs;
930 /* calculate the total size for allocation */
931 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
932 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
933 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
934 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
935 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
936 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
940 /* allocate the shared area */
941 if (sep_map_and_alloc_shared_area(size,
942 &g_sep_shared_area_addr,
943 &g_sep_phys_shared_area_addr)) {
945 /* allocation failed */
946 goto end_function_unmap_io_memory;
949 /* now set the memory regions */
950 g_message_shared_area_addr = g_sep_shared_area_addr;
952 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
953 "SEP Driver: g_message_shared_area_addr is %08lx\n",
954 g_message_shared_area_addr);
956 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
958 /* send the new SHARED MESSAGE AREA to the SEP */
959 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_HOST_SEP_GPR1_REG_ADDR,
960 g_sep_phys_shared_area_addr);
962 /* poll for SEP response */
963 SEP_READ_REGISTER(g_sep_reg_base_address + HW_HOST_SEP_HOST_GPR1_REG_ADDR,
965 while (retVal != 0xffffffff && retVal != g_sep_phys_shared_area_addr)
966 SEP_READ_REGISTER(g_sep_reg_base_address +
967 HW_HOST_SEP_HOST_GPR1_REG_ADDR,
970 /* check the return value (register) */
971 if (retVal != g_sep_phys_shared_area_addr) {
973 goto end_function_deallocate_message_area;
978 /* init the flow contextes */
979 for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
980 g_sep_flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
982 g_sep_flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
983 if (g_sep_flow_wq_ptr == 0) {
985 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
986 "sep_driver:flow queue creation failed\n");
987 goto end_function_deallocate_sep_shared_area;
990 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
991 "SEP Driver: create flow workqueue \n");
993 /* register driver to fs */
994 ret_val = sep_register_driver_to_fs();
996 goto end_function_deallocate_sep_shared_area;
998 /* load the rom code */
1003 end_function_unregister_from_fs:
1005 /* unregister from fs */
1006 sep_unregister_driver_from_fs();
1008 end_function_deallocate_sep_shared_area:
1010 /* de-allocate shared area */
1011 sep_unmap_and_free_shared_area(size,
1012 g_sep_shared_area_addr,
1013 g_sep_phys_shared_area_addr);
1015 end_function_unmap_io_memory:
1017 iounmap((void *)g_sep_reg_base_address);
1019 /* release io memory region */
1020 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1024 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- Init end\n");
1032 /*-------------------------------------------------------------
1034 --------------------------------------------------------------*/
1035 static void __exit sep_exit(void)
1040 /*-----------------------------
1042 --------------------------------*/
1044 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> Exit start\n");
1046 /* unregister from fs */
1047 sep_unregister_driver_from_fs();
1049 /* calculate the total size for de-allocation */
1050 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
1051 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
1052 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
1053 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
1054 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
1055 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
1058 /* free shared area */
1059 sep_unmap_and_free_shared_area(size,
1060 g_sep_shared_area_addr,
1061 g_sep_phys_shared_area_addr);
1063 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1064 "SEP Driver: free pages SEP SHARED AREA \n");
1066 iounmap((void *)g_sep_reg_base_address);
1068 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: iounmap \n");
1070 /* release io memory region */
1071 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1073 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: release_mem_region \n");
1075 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- Exit end\n");
1080 interrupt handler function
1082 irqreturn_t sep_inthandler(int irq, void *dev_id)
1085 irqreturn_t int_error;
1088 unsigned long error;
1091 unsigned long reg_val;
1094 unsigned long flow_id;
1097 struct sep_flow_context_t *flow_context_ptr;
1099 /*-----------------------------
1101 -----------------------------*/
1103 int_error = IRQ_HANDLED;
1105 /* read the IRR register to check if this is SEP interrupt */
1106 SEP_READ_REGISTER(g_sep_reg_base_address + HW_HOST_IRR_REG_ADDR, reg_val);
1107 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Interrupt - reg is %08lx\n",
1110 /* check if this is the flow interrupt */
1111 if (0/*reg_val & (0x1 << 11)*/) {
1112 /* read GPRO to find out the which flow is done */
1113 SEP_READ_REGISTER(g_sep_reg_base_address + HW_HOST_IRR_REG_ADDR,
1116 /* find the contex of the flow */
1117 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
1119 goto end_function_with_error;
1121 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
1123 /* queue the work */
1124 queue_work(g_sep_flow_wq_ptr, &flow_context_ptr->flow_wq);
1127 /* check if this is reply interrupt from SEP */
1128 if (reg_val & (0x1 << 13)) {
1129 /* update the counter of reply messages */
1130 sep_sep_to_host_reply_counter++;
1132 /* wake up the waiting process */
1133 wake_up(&g_sep_event);
1135 int_error = IRQ_NONE;
1140 end_function_with_error:
1142 /* clear the interrupt */
1143 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_ICR_REG_ADDR, reg_val);
1152 This function prepares only input DMA table for synhronic symmetric
1155 int sep_prepare_input_dma_table(unsigned long app_virt_addr,
1156 unsigned long data_size,
1157 unsigned long block_size,
1158 unsigned long *lli_table_ptr,
1159 unsigned long *num_entries_ptr,
1160 unsigned long *table_data_size_ptr,
1161 bool isKernelVirtualAddress)
1164 /* pointer to the info entry of the table - the last entry */
1165 struct sep_lli_entry_t *info_entry_ptr;
1167 /* array of pointers ot page */
1168 struct sep_lli_entry_t *lli_array_ptr;
1170 /* points to the first entry to be processed in the lli_in_array */
1171 unsigned long current_entry;
1173 /* num entries in the virtual buffer */
1174 unsigned long sep_lli_entries;
1176 /* lli table pointer */
1177 struct sep_lli_entry_t *in_lli_table_ptr;
1179 /* the total data in one table */
1180 unsigned long table_data_size;
1182 /* number of entries in lli table */
1183 unsigned long num_entries_in_table;
1185 /* next table address */
1186 unsigned long lli_table_alloc_addr;
1189 unsigned long result;
1191 /*------------------------
1193 --------------------------*/
1195 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1196 "SEP Driver:--------> sep_prepare_input_dma_table start\n");
1198 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:data_size is %lu\n",
1200 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:block_size is %lu\n",
1203 /* initialize the pages pointers */
1204 sep_in_page_array = 0;
1205 sep_in_num_pages = 0;
1207 if (data_size == 0) {
1208 /* special case - created 2 entries table with zero data */
1209 in_lli_table_ptr = (struct sep_lli_entry_t *)(g_sep_shared_area_addr +
1210 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1211 in_lli_table_ptr->physical_address = g_sep_shared_area_addr +
1212 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1213 in_lli_table_ptr->block_size = 0;
1216 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1217 in_lli_table_ptr->block_size = 0;
1219 *lli_table_ptr = g_sep_phys_shared_area_addr +
1220 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1221 *num_entries_ptr = 2;
1222 *table_data_size_ptr = 0;
1227 /* check if the pages are in Kernel Virtual Address layout */
1228 if (isKernelVirtualAddress == true)
1229 /* lock the pages of the kernel buffer and translate them to pages */
1230 result = sep_lock_kernel_pages(app_virt_addr,
1234 &sep_in_page_array);
1236 /* lock the pages of the user buffer and translate them to pages */
1237 result = sep_lock_user_pages(app_virt_addr,
1241 &sep_in_page_array);
1246 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1247 "SEP Driver:output sep_in_num_pages is %lu\n",
1252 sep_lli_entries = sep_in_num_pages;
1254 /* initiate to point after the message area */
1255 lli_table_alloc_addr = g_sep_shared_area_addr +
1256 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1258 /* loop till all the entries in in array are not processed */
1259 while (current_entry < sep_lli_entries) {
1260 /* set the new input and output tables */
1261 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1263 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1264 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1266 /* calculate the maximum size of data for input table */
1267 table_data_size = sep_calculate_lli_table_max_size(
1268 &lli_array_ptr[current_entry],
1269 (sep_lli_entries - current_entry));
1271 /* now calculate the table size so that it will be module block size */
1272 table_data_size = (table_data_size / block_size) * block_size;
1274 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1275 "SEP Driver:output table_data_size is %lu\n",
1278 /* construct input lli table */
1279 sep_build_lli_table(&lli_array_ptr[current_entry],
1282 &num_entries_in_table,
1285 if (info_entry_ptr == 0) {
1286 /* set the output parameters to physical addresses */
1287 *lli_table_ptr = sep_shared_area_virt_to_phys(
1288 (unsigned long)in_lli_table_ptr);
1289 *num_entries_ptr = num_entries_in_table;
1290 *table_data_size_ptr = table_data_size;
1292 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1293 "SEP Driver:output lli_table_in_ptr is %08lx\n",
1296 /* update the info entry of the previous in table */
1297 info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
1298 (unsigned long)in_lli_table_ptr);
1299 info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
1303 /* save the pointer to the info entry of the current tables */
1304 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1307 /* print input tables */
1308 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1309 sep_shared_area_phys_to_virt(*lli_table_ptr),
1311 *table_data_size_ptr);
1313 /* the array of the pages */
1314 kfree(lli_array_ptr);
1318 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1319 "SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1326 This function builds input and output DMA tables for synhronic
1327 symmetric operations (AES, DES). It also checks that each table
1328 is of the modular block size
1330 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
1331 unsigned long app_virt_out_addr,
1332 unsigned long data_size,
1333 unsigned long block_size,
1334 unsigned long *lli_table_in_ptr,
1335 unsigned long *lli_table_out_ptr,
1336 unsigned long *in_num_entries_ptr,
1337 unsigned long *out_num_entries_ptr,
1338 unsigned long *table_data_size_ptr,
1339 bool isKernelVirtualAddress)
1342 /* array of pointers of page */
1343 struct sep_lli_entry_t *lli_in_array;
1345 /* array of pointers of page */
1346 struct sep_lli_entry_t *lli_out_array;
1352 /*------------------------
1354 --------------------------*/
1356 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1357 "SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1361 /* initialize the pages pointers */
1362 sep_in_page_array = 0;
1363 sep_out_page_array = 0;
1365 /* check if the pages are in Kernel Virtual Address layout */
1366 if (isKernelVirtualAddress == true) {
1367 /* lock the pages of the kernel buffer and translate them to pages */
1368 result = sep_lock_kernel_pages(app_virt_in_addr,
1372 &sep_in_page_array);
1374 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1375 "SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1379 /* lock the pages of the user buffer and translate them to pages */
1380 result = sep_lock_user_pages(app_virt_in_addr,
1384 &sep_in_page_array);
1386 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1387 "SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1392 if (isKernelVirtualAddress == true) {
1393 result = sep_lock_kernel_pages(app_virt_out_addr,
1397 &sep_out_page_array);
1399 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1400 "SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1401 goto end_function_with_error1;
1404 result = sep_lock_user_pages(app_virt_out_addr,
1408 &sep_out_page_array);
1410 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1411 "SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1412 goto end_function_with_error1;
1417 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1418 "sep_in_num_pages is %lu\n", sep_in_num_pages);
1419 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1420 "sep_out_num_pages is %lu\n", sep_out_num_pages);
1421 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1422 "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
1423 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1426 /* call the fucntion that creates table from the lli arrays */
1427 result = sep_construct_dma_tables_from_lli(lli_in_array,
1435 out_num_entries_ptr,
1436 table_data_size_ptr);
1438 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1439 "SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1440 goto end_function_with_error2;
1443 /* fall through - free the lli entry arrays */
1445 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "in_num_entries_ptr is %08lx\n",
1446 *in_num_entries_ptr);
1447 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "out_num_entries_ptr is %08lx\n",
1448 *out_num_entries_ptr);
1449 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "table_data_size_ptr is %08lx\n",
1450 *table_data_size_ptr);
1453 end_function_with_error2:
1455 kfree(lli_out_array);
1457 end_function_with_error1:
1459 kfree(lli_in_array);
1463 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1464 "SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n",
1473 This function creates the input and output dma tables for
1474 symmetric operations (AES/DES) according to the block size from LLI arays
1476 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
1477 unsigned long sep_in_lli_entries,
1478 struct sep_lli_entry_t *lli_out_array,
1479 unsigned long sep_out_lli_entries,
1480 unsigned long block_size,
1481 unsigned long *lli_table_in_ptr,
1482 unsigned long *lli_table_out_ptr,
1483 unsigned long *in_num_entries_ptr,
1484 unsigned long *out_num_entries_ptr,
1485 unsigned long *table_data_size_ptr)
1487 /* points to the area where next lli table can be allocated */
1488 unsigned long lli_table_alloc_addr;
1490 /* input lli table */
1491 struct sep_lli_entry_t *in_lli_table_ptr;
1493 /* output lli table */
1494 struct sep_lli_entry_t *out_lli_table_ptr;
1496 /* pointer to the info entry of the table - the last entry */
1497 struct sep_lli_entry_t *info_in_entry_ptr;
1499 /* pointer to the info entry of the table - the last entry */
1500 struct sep_lli_entry_t *info_out_entry_ptr;
1502 /* points to the first entry to be processed in the lli_in_array */
1503 unsigned long current_in_entry;
1505 /* points to the first entry to be processed in the lli_out_array */
1506 unsigned long current_out_entry;
1508 /* max size of the input table */
1509 unsigned long in_table_data_size;
1511 /* max size of the output table */
1512 unsigned long out_table_data_size;
1514 /* flag te signifies if this is the first tables build from the arrays */
1515 unsigned long first_table_flag;
1517 /* the data size that should be in table */
1518 unsigned long table_data_size;
1520 /* number of etnries in the input table */
1521 unsigned long num_entries_in_table;
1523 /* number of etnries in the output table */
1524 unsigned long num_entries_out_table;
1526 /*---------------------
1528 ------------------------*/
1530 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1531 "SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1533 /* initiate to pint after the message area */
1534 lli_table_alloc_addr = g_sep_shared_area_addr +
1535 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1537 current_in_entry = 0;
1538 current_out_entry = 0;
1539 first_table_flag = 1;
1540 info_in_entry_ptr = 0;
1541 info_out_entry_ptr = 0;
1543 /* loop till all the entries in in array are not processed */
1544 while (current_in_entry < sep_in_lli_entries) {
1545 /* set the new input and output tables */
1546 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1548 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1549 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1551 /* set the first output tables */
1552 out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1554 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1555 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1557 /* calculate the maximum size of data for input table */
1558 in_table_data_size =
1559 sep_calculate_lli_table_max_size(
1560 &lli_in_array[current_in_entry],
1561 (sep_in_lli_entries - current_in_entry));
1563 /* calculate the maximum size of data for output table */
1564 out_table_data_size =
1565 sep_calculate_lli_table_max_size(
1566 &lli_out_array[current_out_entry],
1567 (sep_out_lli_entries - current_out_entry));
1569 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1570 "SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1571 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1572 "SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1574 /* check where the data is smallest */
1575 table_data_size = in_table_data_size;
1576 if (table_data_size > out_table_data_size)
1577 table_data_size = out_table_data_size;
1579 /* now calculate the table size so that it will be module block size */
1580 table_data_size = (table_data_size / block_size) * block_size;
1582 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1583 "SEP Driver:table_data_size is %lu\n",
1586 /* construct input lli table */
1587 sep_build_lli_table(&lli_in_array[current_in_entry],
1590 &num_entries_in_table,
1593 /* construct output lli table */
1594 sep_build_lli_table(&lli_out_array[current_out_entry],
1597 &num_entries_out_table,
1600 /* if info entry is null - this is the first table built */
1601 if (info_in_entry_ptr == 0) {
1602 /* set the output parameters to physical addresses */
1604 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1605 *in_num_entries_ptr = num_entries_in_table;
1606 *lli_table_out_ptr =
1607 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1608 *out_num_entries_ptr = num_entries_out_table;
1609 *table_data_size_ptr = table_data_size;
1611 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1612 "SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1613 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1614 "SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1616 /* update the info entry of the previous in table */
1617 info_in_entry_ptr->physical_address =
1618 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1619 info_in_entry_ptr->block_size =
1620 ((num_entries_in_table) << 24) | (table_data_size);
1622 /* update the info entry of the previous in table */
1623 info_out_entry_ptr->physical_address =
1624 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1625 info_out_entry_ptr->block_size =
1626 ((num_entries_out_table) << 24) | (table_data_size);
1629 /* save the pointer to the info entry of the current tables */
1630 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1631 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1633 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1634 "SEP Driver:output num_entries_out_table is %lu\n",
1635 (unsigned long)num_entries_out_table);
1636 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1637 "SEP Driver:output info_in_entry_ptr is %lu\n",
1638 (unsigned long)info_in_entry_ptr);
1639 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1640 "SEP Driver:output info_out_entry_ptr is %lu\n",
1641 (unsigned long)info_out_entry_ptr);
1644 /* print input tables */
1645 sep_debug_print_lli_tables(
1646 (struct sep_lli_entry_t *)
1647 sep_shared_area_phys_to_virt(*lli_table_in_ptr),
1648 *in_num_entries_ptr,
1649 *table_data_size_ptr);
1651 /* print output tables */
1652 sep_debug_print_lli_tables(
1653 (struct sep_lli_entry_t *)
1654 sep_shared_area_phys_to_virt(*lli_table_out_ptr),
1655 *out_num_entries_ptr,
1656 *table_data_size_ptr);
1658 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1659 "SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1665 this function calculates the size of data that can be inserted into the lli
1666 table from this array the condition is that either the table is full
1667 (all etnries are entered), or there are no more entries in the lli array
1669 unsigned long sep_calculate_lli_table_max_size(
1670 struct sep_lli_entry_t *lli_in_array_ptr,
1671 unsigned long num_array_entries)
1673 /* table data size */
1674 unsigned long table_data_size;
1677 unsigned long counter;
1679 /*---------------------
1681 ----------------------*/
1683 table_data_size = 0;
1685 /* calculate the data in the out lli table if till we fill the whole
1686 table or till the data has ended */
1688 (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
1689 (counter < num_array_entries); counter++)
1690 table_data_size += lli_in_array_ptr[counter].block_size;
1692 return table_data_size;
1696 this functions builds ont lli table from the lli_array according to
1697 the given size of data
1699 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
1700 struct sep_lli_entry_t *lli_table_ptr,
1701 unsigned long *num_processed_entries_ptr,
1702 unsigned long *num_table_entries_ptr,
1703 unsigned long table_data_size)
1705 /* current table data size */
1706 unsigned long curr_table_data_size;
1708 /* counter of lli array entry */
1709 unsigned long array_counter;
1711 /*-----------------------
1713 ---------------------------*/
1715 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1716 "SEP Driver:--------> sep_build_lli_table start\n");
1718 /* init currrent table data size and lli array entry counter */
1719 curr_table_data_size = 0;
1721 *num_table_entries_ptr = 1;
1723 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1724 "SEP Driver:table_data_size is %lu\n",
1727 /* fill the table till table size reaches the needed amount */
1728 while (curr_table_data_size < table_data_size) {
1729 /* update the number of entries in table */
1730 (*num_table_entries_ptr)++;
1732 lli_table_ptr->physical_address =
1733 lli_array_ptr[array_counter].physical_address;
1734 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1735 curr_table_data_size += lli_table_ptr->block_size;
1737 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1738 "SEP Driver:lli_table_ptr is %08lx\n",
1739 (unsigned long)lli_table_ptr);
1740 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1741 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1742 lli_table_ptr->physical_address);
1743 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1744 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1745 lli_table_ptr->block_size);
1747 /* check for overflow of the table data */
1748 if (curr_table_data_size > table_data_size) {
1749 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1750 "SEP Driver:curr_table_data_size > table_data_size\n");
1752 /* update the size of block in the table */
1753 lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1755 /* update the physical address in the lli array */
1756 lli_array_ptr[array_counter].physical_address +=
1757 lli_table_ptr->block_size;
1759 /* update the block size left in the lli array */
1760 lli_array_ptr[array_counter].block_size =
1761 (curr_table_data_size - table_data_size);
1763 /* advance to the next entry in the lli_array */
1766 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1767 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1768 lli_table_ptr->physical_address);
1769 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1770 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1771 lli_table_ptr->block_size);
1773 /* move to the next entry in table */
1777 /* set the info entry to default */
1778 lli_table_ptr->physical_address = 0xffffffff;
1779 lli_table_ptr->block_size = 0;
1781 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1782 "SEP Driver:lli_table_ptr is %08lx\n",
1783 (unsigned long)lli_table_ptr);
1784 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1785 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1786 lli_table_ptr->physical_address);
1787 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1788 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1789 lli_table_ptr->block_size);
1792 /* set the output parameter */
1793 *num_processed_entries_ptr += array_counter;
1795 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1796 "SEP Driver:*num_processed_entries_ptr is %lu\n",
1797 *num_processed_entries_ptr);
1800 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1801 "SEP Driver:<-------- sep_build_lli_table end\n");
1807 this function goes over the list of the print created tables and
1810 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
1811 unsigned long num_table_entries,
1812 unsigned long table_data_size)
1814 unsigned long table_count;
1816 unsigned long entries_count;
1817 /*-----------------------------
1819 -------------------------------*/
1821 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1822 "SEP Driver:--------> sep_debug_print_lli_tables start\n");
1825 while ((unsigned long)lli_table_ptr != 0xffffffff) {
1826 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1827 "SEP Driver: lli table %08lx, table_data_size is %lu\n",
1830 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1831 "SEP Driver: num_table_entries is %lu\n", num_table_entries);
1833 /* print entries of the table (without info entry) */
1834 for (entries_count = 0;
1835 entries_count < num_table_entries;
1836 entries_count++, lli_table_ptr++) {
1837 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1838 "SEP Driver:lli_table_ptr address is %08lx\n",
1839 (unsigned long)lli_table_ptr);
1840 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1841 "SEP Driver:phys address is %08lx block size is %lu\n",
1842 lli_table_ptr->physical_address, lli_table_ptr->block_size);
1845 /* point to the info entry */
1848 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1849 "SEP Driver:phys lli_table_ptr->block_size is %lu\n",
1850 lli_table_ptr->block_size);
1851 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1852 "SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
1853 lli_table_ptr->physical_address);
1856 table_data_size = lli_table_ptr->block_size & 0xffffff;
1857 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1858 lli_table_ptr = (struct sep_lli_entry_t *)
1859 (lli_table_ptr->physical_address);
1861 DEBUG_PRINT_3(SEP_DEBUG_LEVEL_EXTENDED,
1862 "SEP Driver:phys table_data_size is %lu num_table_entries is \
1863 %lu lli_table_ptr is%lu\n",
1864 table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
1866 if ((unsigned long)lli_table_ptr != 0xffffffff)
1867 lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
1868 (unsigned long)lli_table_ptr);
1873 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1874 "SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1879 This function locks all the physical pages of the application virtual buffer
1880 and construct a basic lli array, where each entry holds the physical page
1881 address and the size that application data holds in this physical pages
1883 int sep_lock_user_pages(unsigned long app_virt_addr,
1884 unsigned long data_size,
1885 unsigned long *num_pages_ptr,
1886 struct sep_lli_entry_t **lli_array_ptr,
1887 struct page ***page_array_ptr)
1893 /* the the page of the end address of the user space buffer */
1894 unsigned long end_page;
1896 /* the page of the start address of the user space buffer */
1897 unsigned long start_page;
1899 /* the range in pages */
1900 unsigned long num_pages;
1902 /* array of pointers ot page */
1903 struct page **page_array;
1906 struct sep_lli_entry_t *lli_array;
1909 unsigned long count;
1914 /*------------------------
1916 --------------------------*/
1918 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1919 "SEP Driver:--------> sep_lock_user_pages start\n");
1923 /* set start and end pages and num pages */
1924 end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1925 start_page = app_virt_addr >> PAGE_SHIFT;
1926 num_pages = end_page - start_page + 1;
1928 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1929 "SEP Driver: app_virt_addr is %08lx\n",
1931 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1932 "SEP Driver: data_size is %lu\n",
1934 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1935 "SEP Driver: start_page is %lu\n",
1937 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1938 "SEP Driver: end_page is %lu\n",
1940 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1941 "SEP Driver: num_pages is %lu\n",
1944 /* allocate array of pages structure pointers */
1945 page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1947 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1948 "SEP Driver: kmalloc for page_array failed\n");
1954 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1956 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1957 "SEP Driver: kmalloc for lli_array failed\n");
1960 goto end_function_with_error1;
1963 /* convert the application virtual address into a set of physical */
1964 down_read(¤t->mm->mmap_sem);
1965 result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
1968 up_read(¤t->mm->mmap_sem);
1970 /* check the number of pages locked - if not all then exit with error */
1971 if (result != num_pages) {
1972 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1973 "SEP Driver: not all pages locked by get_user_pages\n");
1976 goto end_function_with_error2;
1979 /* flush the cache */
1980 for (count = 0; count < num_pages; count++)
1981 flush_dcache_page(page_array[count]);
1983 /* set the start address of the first page - app data may start not at
1984 the beginning of the page */
1985 lli_array[0].physical_address = (
1986 (unsigned long)page_to_phys(page_array[0])) +
1987 (app_virt_addr & (~PAGE_MASK)) ;
1989 /* check that not all the data is in the first page only */
1990 if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1991 lli_array[0].block_size = data_size;
1993 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1996 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1997 "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
1998 lli_array[0].physical_address,
1999 lli_array[0].block_size);
2001 /* go from the second page to the prev before last */
2002 for (count = 1; count < (num_pages - 1); count++) {
2003 lli_array[count].physical_address =
2004 (unsigned long)page_to_phys(page_array[count]);
2005 lli_array[count].block_size = PAGE_SIZE;
2007 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2008 "lli_array[%lu].physical_address is %08lx, \
2009 lli_array[%lu].block_size is %lu\n",
2010 count, lli_array[count].physical_address,
2012 lli_array[count].block_size);
2015 /* if more then 1 pages locked - then update for the last page size needed */
2016 if (num_pages > 1) {
2017 /* update the address of the last page */
2018 lli_array[count].physical_address =
2019 (unsigned long)page_to_phys(page_array[count]);
2021 /* set the size of the last page */
2022 lli_array[count].block_size = (app_virt_addr + data_size) &
2025 if (lli_array[count].block_size == 0) {
2026 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
2027 "app_virt_addr is %08lx\n",
2029 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
2032 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2033 "lli_array[%lu].physical_address is %08lx, \
2034 lli_array[%lu].block_size is %lu\n",
2035 count, lli_array[count].physical_address,
2037 lli_array[count].block_size);
2040 /* set output params */
2041 *lli_array_ptr = lli_array;
2042 *num_pages_ptr = num_pages;
2043 *page_array_ptr = page_array;
2047 end_function_with_error2:
2049 /* release the cache */
2050 for (count = 0; count < num_pages; count++)
2051 page_cache_release(page_array[count]);
2053 /* free lli array */
2056 end_function_with_error1:
2058 /* free page array */
2063 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2064 "SEP Driver:<-------- sep_lock_user_pages end\n");
2070 This function locks all the physical pages of the kernel virtual buffer
2071 and construct a basic lli array, where each entry holds the physical
2072 page address and the size that application data holds in this physical pages
2074 int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
2075 unsigned long data_size,
2076 unsigned long *num_pages_ptr,
2077 struct sep_lli_entry_t **lli_array_ptr,
2078 struct page ***page_array_ptr)
2084 /* the the page of the end address of the user space buffer */
2085 unsigned long end_page;
2087 /* the page of the start address of the user space buffer */
2088 unsigned long start_page;
2090 /* the range in pages */
2091 unsigned long num_pages;
2094 struct sep_lli_entry_t *lli_array;
2096 /* next kernel address to map */
2097 unsigned long next_kernel_address;
2100 unsigned long count;
2103 /*------------------------
2105 --------------------------*/
2107 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2108 "SEP Driver:--------> sep_lock_kernel_pages start\n");
2112 /* set start and end pages and num pages */
2113 end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
2114 start_page = kernel_virt_addr >> PAGE_SHIFT;
2115 num_pages = end_page - start_page + 1;
2117 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2118 "SEP Driver: kernel_virt_addr is %08lx\n",
2120 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2121 "SEP Driver: data_size is %lu\n",
2123 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2124 "SEP Driver: start_page is %lx\n",
2126 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2127 "SEP Driver: end_page is %lx\n",
2129 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2130 "SEP Driver: num_pages is %lu\n",
2133 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
2135 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
2136 "SEP Driver: kmalloc for lli_array failed\n");
2142 /* set the start address of the first page - app data may start not at
2143 the beginning of the page */
2144 lli_array[0].physical_address =
2145 (unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
2147 /* check that not all the data is in the first page only */
2148 if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
2149 lli_array[0].block_size = data_size;
2151 lli_array[0].block_size =
2152 PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
2155 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2156 "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
2157 lli_array[0].physical_address,
2158 lli_array[0].block_size);
2160 /* advance the address to the start of the next page */
2161 next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
2163 /* go from the second page to the prev before last */
2164 for (count = 1; count < (num_pages - 1); count++) {
2165 lli_array[count].physical_address =
2166 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2167 lli_array[count].block_size = PAGE_SIZE;
2169 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2170 "lli_array[%lu].physical_address is %08lx, \
2171 lli_array[%lu].block_size is %lu\n",
2172 count, lli_array[count].physical_address, count,
2173 lli_array[count].block_size);
2175 next_kernel_address += PAGE_SIZE;
2178 /* if more then 1 pages locked - then update for the last page size needed */
2179 if (num_pages > 1) {
2180 /* update the address of the last page */
2181 lli_array[count].physical_address =
2182 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2184 /* set the size of the last page */
2185 lli_array[count].block_size =
2186 (kernel_virt_addr + data_size) & (~PAGE_MASK);
2188 if (lli_array[count].block_size == 0) {
2189 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
2190 "app_virt_addr is %08lx\n",
2192 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
2196 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2197 "lli_array[%lu].physical_address is %08lx, \
2198 lli_array[%lu].block_size is %lu\n",
2199 count, lli_array[count].physical_address,
2201 lli_array[count].block_size);
2204 /* set output params */
2205 *lli_array_ptr = lli_array;
2206 *num_pages_ptr = num_pages;
2207 *page_array_ptr = 0;
2212 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2213 "SEP Driver:<-------- sep_lock_kernel_pages end\n");
2219 This function releases all the application virtual buffer physical pages,
2220 that were previously locked
2222 int sep_free_dma_pages(struct page **page_array_ptr,
2223 unsigned long num_pages,
2224 unsigned long dirtyFlag)
2227 unsigned long count;
2229 /*-------------------
2231 ---------------------*/
2234 for (count = 0; count < num_pages; count++) {
2235 /* the out array was written, therefore the data was changed */
2236 if (!PageReserved(page_array_ptr[count]))
2237 SetPageDirty(page_array_ptr[count]);
2238 page_cache_release(page_array_ptr[count]);
2241 /* free in pages - the data was only read, therefore no update was done
2243 for (count = 0; count < num_pages; count++)
2244 page_cache_release(page_array_ptr[count]);
2248 /* free the array */
2249 kfree(page_array_ptr);
2255 This function raises interrupt to SEP that signals that is has a new
2258 static void sep_send_command_handler()
2261 unsigned long count;
2263 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2264 "SEP Driver:--------> sep_send_command_handler start\n");
2271 for (count = 0; count < 12 * 4; count += 4)
2272 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2273 "Word %lu of the message is %lu\n",
2275 *((unsigned long *)(g_sep_shared_area_addr + count)));
2277 /* update counter */
2278 sep_host_to_sep_send_counter++;
2280 /* send interrupt to SEP */
2281 SEP_WRITE_REGISTER(g_sep_reg_base_address +
2282 HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2284 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2285 "SEP Driver:<-------- sep_send_command_handler end\n");
2291 This function raises interrupt to SEPm that signals that is has a
2292 new command from HOST
2294 static void sep_send_reply_command_handler()
2296 unsigned long count;
2298 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2299 "SEP Driver:--------> sep_send_reply_command_handler start\n");
2304 for (count = 0; count < 12 * 4; count += 4)
2305 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2306 "Word %lu of the message is %lu\n",
2308 *((unsigned long *)(g_sep_shared_area_addr + count)));
2311 /* update counter */
2312 sep_host_to_sep_send_counter++;
2314 /* send the interrupt to SEP */
2315 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_HOST_SEP_GPR2_REG_ADDR,
2316 sep_host_to_sep_send_counter);
2318 /* update both counters */
2319 sep_host_to_sep_send_counter++;
2321 sep_sep_to_host_reply_counter++;
2323 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2324 "SEP Driver:<-------- sep_send_reply_command_handler end\n");
2332 This function handles the allocate data pool memory request
2333 This function returns calculates the physical address of the
2334 allocated memory, and the offset of this area from the mapped address.
2335 Therefore, the FVOs in user space can calculate the exact virtual
2336 address of this allocated memory
2338 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
2343 /* command paramaters */
2344 struct sep_driver_alloc_t command_args;
2346 /*-------------------------
2348 ----------------------------*/
2350 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2351 "SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
2354 error = copy_from_user(&command_args,
2356 sizeof(struct sep_driver_alloc_t));
2360 /* allocate memory */
2362 (sep_data_pool_bytes_allocated + command_args.num_bytes) >
2363 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
2368 /* set the virtual and physical address */
2369 command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2370 sep_data_pool_bytes_allocated;
2371 command_args.phys_address = g_sep_phys_shared_area_addr +
2372 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2373 sep_data_pool_bytes_allocated;
2375 /* write the memory back to the user space */
2376 error = copy_to_user((void *)arg,
2377 (void *)&command_args,
2378 sizeof(struct sep_driver_alloc_t));
2382 /* set the allocation */
2383 sep_data_pool_bytes_allocated += command_args.num_bytes;
2387 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2388 "SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
2394 This function handles write into allocated data pool command
2396 static int sep_write_into_data_pool_handler(unsigned long arg)
2401 /* virtual address */
2402 unsigned long virt_address;
2404 /* application in address */
2405 unsigned long app_in_address;
2407 /* number of bytes */
2408 unsigned long num_bytes;
2410 /* address of the data pool */
2411 unsigned long data_pool_area_addr;
2413 /*--------------------------
2415 -----------------------------*/
2417 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2418 "SEP Driver:--------> sep_write_into_data_pool_handler start\n");
2420 /* get the application address */
2421 error = get_user(app_in_address,
2422 &(((struct sep_driver_write_t *)arg)->app_address));
2426 /* get the virtual kernel address address */
2427 error = get_user(virt_address,
2428 &(((struct sep_driver_write_t *)arg)->datapool_address));
2432 /* get the number of bytes */
2433 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2437 /* calculate the start of the data pool */
2438 data_pool_area_addr = g_sep_shared_area_addr +
2439 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2442 /* check that the range of the virtual kernel address is correct */
2443 if ((virt_address < data_pool_area_addr) ||
2444 (virt_address > (data_pool_area_addr +
2445 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2450 /* copy the application data */
2451 error = copy_from_user((void *)virt_address,
2452 (void *)app_in_address,
2457 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2458 "SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
2464 this function handles the read from data pool command
2466 static int sep_read_from_data_pool_handler(unsigned long arg)
2471 /* virtual address of dest application buffer */
2472 unsigned long app_out_address;
2474 /* virtual address of the data pool */
2475 unsigned long virt_address;
2478 unsigned long num_bytes;
2480 /* address of the data pool */
2481 unsigned long data_pool_area_addr;
2483 /*------------------------
2485 -----------------------------*/
2487 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2488 "SEP Driver:--------> sep_read_from_data_pool_handler start\n");
2490 /* get the application address */
2491 error = get_user(app_out_address,
2492 &(((struct sep_driver_write_t *)arg)->app_address));
2496 /* get the virtual kernel address address */
2497 error = get_user(virt_address,
2498 &(((struct sep_driver_write_t *)arg)->datapool_address));
2502 /* get the number of bytes */
2503 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2507 /* calculate the start of the data pool */
2508 data_pool_area_addr = g_sep_shared_area_addr +
2509 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2511 /* check that the range of the virtual kernel address is correct */
2512 if ((virt_address < data_pool_area_addr) ||
2513 (virt_address > (data_pool_area_addr +
2514 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2519 /* copy the application data */
2520 error = copy_to_user((void *)app_out_address, (void *)virt_address,
2525 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2526 "SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
2533 this function handles tha request for creation of the DMA table
2534 for the synchronic symmetric operations (AES,DES)
2536 static int sep_create_sync_dma_tables_handler(unsigned long arg)
2541 /* command arguments */
2542 struct sep_driver_build_sync_table_t command_args;
2544 /*------------------------
2546 --------------------------*/
2548 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2549 "SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
2551 error = copy_from_user(&command_args,
2553 sizeof(struct sep_driver_build_sync_table_t));
2557 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2558 "app_in_address is %08lx\n",
2559 command_args.app_in_address);
2560 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2561 "app_out_address is %08lx\n",
2562 command_args.app_out_address);
2563 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2564 "data_size is %lu\n",
2565 command_args.data_in_size);
2566 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2567 "block_size is %lu\n",
2568 command_args.block_size);
2571 /* check if we need to build only input table or input/output */
2572 if (command_args.app_out_address)
2573 /* prepare input and output tables */
2574 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
2575 command_args.app_out_address,
2576 command_args.data_in_size,
2577 command_args.block_size,
2578 &command_args.in_table_address,
2579 &command_args.out_table_address,
2580 &command_args.in_table_num_entries,
2581 &command_args.out_table_num_entries,
2582 &command_args.table_data_size,
2583 command_args.isKernelVirtualAddress);
2585 /* prepare input tables */
2586 error = sep_prepare_input_dma_table(command_args.app_in_address,
2587 command_args.data_in_size,
2588 command_args.block_size,
2589 &command_args.in_table_address,
2590 &command_args.in_table_num_entries,
2591 &command_args.table_data_size,
2592 command_args.isKernelVirtualAddress);
2598 error = copy_to_user((void *)arg,
2599 (void *)&command_args,
2600 sizeof(struct sep_driver_build_sync_table_t));
2604 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2605 "SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
2611 this function handles the request for freeing dma table for synhronic actions
2613 int sep_free_dma_table_data_handler()
2615 /*-------------------------
2617 -----------------------------*/
2619 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2620 "SEP Driver:--------> sep_free_dma_table_data_handler start\n");
2622 /* free input pages array */
2623 sep_free_dma_pages(sep_in_page_array,
2627 /* free output pages array if needed */
2628 if (sep_out_page_array)
2629 sep_free_dma_pages(sep_out_page_array,
2633 /* reset all the values */
2634 sep_in_page_array = 0;
2635 sep_out_page_array = 0;
2636 sep_in_num_pages = 0;
2637 sep_out_num_pages = 0;
2640 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2641 "SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
2647 this function handles the request to create the DMA tables for flow
2649 static int sep_create_flow_dma_tables_handler(unsigned long arg)
2654 /* command arguments */
2655 struct sep_driver_build_flow_table_t command_args;
2657 /* first table - output */
2658 struct sep_lli_entry_t first_table_data;
2660 /* dma table data */
2661 struct sep_lli_entry_t last_table_data;
2663 /* pointer to the info entry of the previuos DMA table */
2664 struct sep_lli_entry_t *prev_info_entry_ptr;
2666 /* pointer to the flow data strucutre */
2667 struct sep_flow_context_t *flow_context_ptr;
2669 /*------------------------
2671 --------------------------*/
2673 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2674 "SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
2676 /* init variables */
2677 prev_info_entry_ptr = 0;
2678 first_table_data.physical_address = 0xffffffff;
2680 /* find the free structure for flow data */
2681 error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
2685 error = copy_from_user(&command_args,
2687 sizeof(struct sep_driver_build_flow_table_t));
2691 /* create flow tables */
2692 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2693 command_args.virt_buff_data_addr,
2697 command_args.isKernelVirtualAddress);
2699 goto end_function_with_error;
2701 /* check if flow is static */
2702 if (!command_args.flow_type)
2703 /* point the info entry of the last to the info entry of the first */
2704 last_table_data = first_table_data;
2706 /* set output params */
2707 command_args.first_table_addr = first_table_data.physical_address;
2708 command_args.first_table_num_entries =
2709 ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
2710 SEP_NUM_ENTRIES_MASK);
2711 command_args.first_table_data_size =
2712 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2714 /* send the parameters to user application */
2715 error = copy_to_user((void *)arg,
2717 sizeof(struct sep_driver_build_flow_table_t));
2719 goto end_function_with_error;
2721 /* all the flow created - update the flow entry with temp id */
2722 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
2724 /* set the processing tables data in the context */
2725 if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
2726 flow_context_ptr->input_tables_in_process = first_table_data;
2728 flow_context_ptr->output_tables_in_process = first_table_data;
2732 end_function_with_error:
2734 /* free the allocated tables */
2735 sep_deallocated_flow_tables(&first_table_data);
2739 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2740 "SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
2747 this functio n handles add tables to flow
2749 static int sep_add_flow_tables_handler(unsigned long arg)
2754 /* number of entries */
2755 unsigned long num_entries;
2757 /* command arguments */
2758 struct sep_driver_add_flow_table_t command_args;
2760 /* pointer to the flow data strucutre */
2761 struct sep_flow_context_t *flow_context_ptr;
2763 /* first dma table data */
2764 struct sep_lli_entry_t first_table_data;
2766 /* last dma table data */
2767 struct sep_lli_entry_t last_table_data;
2769 /* pointer to the info entry of the current DMA table */
2770 struct sep_lli_entry_t *info_entry_ptr;
2772 /*--------------------------
2774 ----------------------------*/
2776 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2777 "SEP Driver:--------> sep_add_flow_tables_handler start\n");
2779 /* get input parameters */
2780 error = copy_from_user(&command_args,
2782 sizeof(struct sep_driver_add_flow_table_t));
2786 /* find the flow structure for the flow id */
2787 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2791 /* prepare the flow dma tables */
2792 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2793 command_args.virt_buff_data_addr,
2797 command_args.isKernelVirtualAddress);
2799 goto end_function_with_error;
2801 /* now check if there is already an existing add table for this flow */
2802 if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
2803 /* this buffer was for input buffers */
2804 if (flow_context_ptr->input_tables_flag) {
2805 /* add table already exists - add the new tables to the end
2807 num_entries = (flow_context_ptr->last_input_table.block_size >>
2808 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2811 (struct sep_lli_entry_t *)
2812 (flow_context_ptr->last_input_table.physical_address +
2813 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2815 /* connect to list of tables */
2816 *info_entry_ptr = first_table_data;
2818 /* set the first table data */
2819 first_table_data = flow_context_ptr->first_input_table;
2821 /* set the input flag */
2822 flow_context_ptr->input_tables_flag = 1;
2824 /* set the first table data */
2825 flow_context_ptr->first_input_table = first_table_data;
2827 /* set the last table data */
2828 flow_context_ptr->last_input_table = last_table_data;
2829 } else /* this is output tables */ {
2830 /* this buffer was for input buffers */
2831 if (flow_context_ptr->output_tables_flag) {
2832 /* add table already exists - add the new tables to
2833 the end of the previous */
2834 num_entries = (flow_context_ptr->last_output_table.block_size >>
2835 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2838 (struct sep_lli_entry_t *)
2839 (flow_context_ptr->last_output_table.physical_address +
2840 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2842 /* connect to list of tables */
2843 *info_entry_ptr = first_table_data;
2845 /* set the first table data */
2846 first_table_data = flow_context_ptr->first_output_table;
2848 /* set the input flag */
2849 flow_context_ptr->output_tables_flag = 1;
2851 /* set the first table data */
2852 flow_context_ptr->first_output_table = first_table_data;
2854 /* set the last table data */
2855 flow_context_ptr->last_output_table = last_table_data;
2858 /* set output params */
2859 command_args.first_table_addr = first_table_data.physical_address;
2860 command_args.first_table_num_entries = ((first_table_data.block_size >>
2861 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
2862 command_args.first_table_data_size =
2863 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2865 /* send the parameters to user application */
2866 error = copy_to_user((void *)arg,
2868 sizeof(struct sep_driver_add_flow_table_t));
2870 goto end_function_with_error;
2872 end_function_with_error:
2874 /* free the allocated tables */
2875 sep_deallocated_flow_tables(&first_table_data);
2879 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2880 "SEP Driver:<-------- sep_add_flow_tables_handler end\n");
2886 this function add the flow add message to the specific flow
2888 static int sep_add_flow_tables_message_handler(unsigned long arg)
2894 struct sep_driver_add_message_t command_args;
2897 struct sep_flow_context_t *flow_context_ptr;
2899 /*----------------------------
2901 ------------------------------*/
2903 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2904 "SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
2906 error = copy_from_user(&command_args,
2908 sizeof(struct sep_driver_add_message_t));
2913 if (command_args.message_size_in_bytes >
2914 SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
2919 /* find the flow context */
2920 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2924 /* copy the message into context */
2925 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
2927 error = copy_from_user(flow_context_ptr->message,
2928 (void *)command_args.message_address,
2929 command_args.message_size_in_bytes);
2934 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2935 "SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
2942 this function returns the physical and virtual addresses of the static pool
2944 static int sep_get_static_pool_addr_handler(unsigned long arg)
2949 /* command arguments */
2950 struct sep_driver_static_pool_addr_t command_args;
2952 /*-----------------------------
2954 ------------------------------*/
2956 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2957 "SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2959 /*prepare the output parameters in the struct */
2960 command_args.physical_static_address = g_sep_phys_shared_area_addr +
2961 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2962 command_args.virtual_static_address = g_sep_shared_area_addr +
2963 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2965 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2966 "SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
2967 command_args.physical_static_address,
2968 command_args.virtual_static_address);
2970 /* send the parameters to user application */
2971 error = copy_to_user((void *)arg,
2973 sizeof(struct sep_driver_static_pool_addr_t));
2979 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2980 "SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2986 this address gets the offset of the physical address from the start
2989 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2994 /* command arguments */
2995 struct sep_driver_get_mapped_offset_t command_args;
2997 /*-----------------------------
2999 ------------------------------*/
3001 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3002 "SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
3004 error = copy_from_user(&command_args,
3006 sizeof(struct sep_driver_get_mapped_offset_t));
3010 if (command_args.physical_address < g_sep_phys_shared_area_addr) {
3015 /*prepare the output parameters in the struct */
3016 command_args.offset = command_args.physical_address -
3017 g_sep_phys_shared_area_addr;
3019 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
3020 "SEP Driver:physical_address is %08lx, offset is %lu\n",
3021 command_args.physical_address,
3022 command_args.offset);
3024 /* send the parameters to user application */
3025 error = copy_to_user((void *)arg,
3027 sizeof(struct sep_driver_get_mapped_offset_t));
3033 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3034 "SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
3043 static int sep_start_handler(void)
3046 unsigned long reg_val;
3049 unsigned long error;
3051 /*-----------------------------
3053 ------------------------------*/
3055 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3056 "SEP Driver:--------> sep_start_handler start\n");
3060 /* wait in polling for message from SEP */
3062 SEP_READ_REGISTER(g_sep_reg_base_address +
3063 HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
3066 /* check the value */
3067 if (reg_val == 0x1) {
3068 /* fatal error - read erro status from GPRO */
3069 SEP_READ_REGISTER(g_sep_reg_base_address +
3070 HW_HOST_SEP_HOST_GPR0_REG_ADDR, error);
3076 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3077 "SEP Driver:<-------- sep_start_handler end\n");
3083 this function handles the request for SEP initialization
3085 static int sep_init_handler(unsigned long arg)
3087 /* word from message */
3088 unsigned long message_word;
3091 unsigned long *message_ptr;
3093 /* command arguments */
3094 struct sep_driver_init_t command_args;
3097 unsigned long counter;
3100 unsigned long error;
3103 unsigned long reg_val;
3105 /*-------------------
3107 ---------------------*/
3109 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3110 "SEP Driver:--------> sep_init_handler start\n");
3114 error = copy_from_user(&command_args, (void *)arg,
3115 sizeof(struct sep_driver_init_t));
3117 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3118 "SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
3123 /* PATCH - configure the DMA to single -burst instead of multi-burst */
3124 /*sep_configure_dma_burst();*/
3126 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3127 "SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
3129 message_ptr = (unsigned long *)command_args.message_addr;
3131 /* set the base address of the SRAM */
3132 SEP_WRITE_REGISTER(g_sep_reg_base_address +
3133 HW_SRAM_ADDR_REG_ADDR,
3134 HW_CC_SRAM_BASE_ADDRESS);
3137 counter < command_args.message_size_in_words;
3138 counter++, message_ptr++) {
3139 get_user(message_word, message_ptr);
3141 /* write data to SRAM */
3142 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_SRAM_DATA_REG_ADDR,
3145 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3146 "SEP Driver:message_word is %lu\n",
3149 /* wait for write complete */
3150 SEP_WAIT_SRAM_WRITE_COMPLETE();
3153 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3154 "SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
3157 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_HOST_SEP_GPR0_REG_ADDR,
3161 SEP_READ_REGISTER(g_sep_reg_base_address +
3162 HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
3163 } while (!(reg_val & 0xFFFFFFFD));
3165 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3166 "SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
3168 /* check the value */
3169 if (reg_val == 0x1) {
3170 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
3171 "SEP Driver:init failed\n");
3173 SEP_READ_REGISTER(g_sep_reg_base_address + 0x8060, error);
3174 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3175 "SEP Driver:sw monitor is %lu\n",
3178 /* fatal error - read erro status from GPRO */
3179 SEP_READ_REGISTER(g_sep_reg_base_address +
3180 HW_HOST_SEP_HOST_GPR0_REG_ADDR,
3182 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3183 "SEP Driver:error is %lu\n", error);
3189 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3190 "SEP Driver:<-------- sep_init_handler end\n");
3197 this function handles the request cache and resident reallocation
3199 static int sep_realloc_cache_resident_handler(unsigned long arg)
3204 /* physical cache addr */
3205 unsigned long phys_cache_address;
3207 /* physical resident addr */
3208 unsigned long phys_resident_address;
3210 /* command arguments */
3211 struct sep_driver_realloc_cache_resident_t command_args;
3213 /*------------------
3215 ---------------------*/
3218 error = copy_from_user(&command_args,
3220 sizeof(struct sep_driver_realloc_cache_resident_t));
3224 /* copy cache and resident to the their intended locations */
3225 error = sep_copy_cache_resident_to_area(command_args.cache_addr,
3226 command_args.cache_size_in_bytes,
3227 command_args.resident_addr,
3228 command_args.resident_size_in_bytes,
3229 &phys_cache_address,
3230 &phys_resident_address);
3234 /* lock the area (if needed) */
3235 sep_lock_cache_resident_area();
3237 command_args.new_base_addr = g_sep_phys_shared_area_addr;
3239 /* find the new base address according to the lowest address between
3240 cache, resident and shared area */
3241 if (phys_resident_address < command_args.new_base_addr)
3242 command_args.new_base_addr = phys_resident_address;
3243 if (phys_cache_address < command_args.new_base_addr)
3244 command_args.new_base_addr = phys_cache_address;
3246 /* set the return parameters */
3247 command_args.new_cache_addr = phys_cache_address;
3248 command_args.new_resident_addr = phys_resident_address;
3251 /* set the new shared area */
3252 command_args.new_shared_area_addr = g_sep_phys_shared_area_addr;
3254 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3255 "SEP Driver:command_args.new_shared_area_addr is %08lx\n",
3256 command_args.new_shared_area_addr);
3257 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3258 "SEP Driver:command_args.new_base_addr is %08lx\n",
3259 command_args.new_base_addr);
3260 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3261 "SEP Driver:command_args.new_resident_addr is %08lx\n",
3262 command_args.new_resident_addr);
3263 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3264 "SEP Driver:command_args.new_cache_addr is %08lx\n",
3265 command_args.new_cache_addr);
3267 /* return to user */
3268 error = copy_to_user((void *)arg,
3269 (void *)&command_args,
3270 sizeof(struct sep_driver_realloc_cache_resident_t));
3278 this function handles the request for get time
3280 static int sep_get_time_handler(unsigned long arg)
3285 /* command arguments */
3286 struct sep_driver_get_time_t command_args;
3288 /*------------------------
3290 --------------------------*/
3292 error = sep_set_time(&command_args.time_physical_address,
3293 &command_args.time_value);
3295 /* return to user */
3296 error = copy_to_user((void *)arg,
3297 (void *)&command_args,
3298 sizeof(struct sep_driver_get_time_t));
3305 This api handles the setting of API mode to blocking or non-blocking
3307 static int sep_set_api_mode_handler(unsigned long arg)
3313 unsigned long mode_flag;
3315 /*----------------------------
3317 -----------------------------*/
3319 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3320 "SEP Driver:--------> sep_set_api_mode_handler start\n");
3323 mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
3327 /* set the global flag */
3328 g_sep_block_mode_flag = mode_flag;
3333 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3334 "SEP Driver:<-------- sep_set_api_mode_handler end\n");
3340 This API handles the end transaction request
3342 static int sep_end_transaction_handler(unsigned long arg)
3344 /*----------------------------
3346 -----------------------------*/
3348 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3349 "SEP Driver:--------> sep_end_transaction_handler start\n");
3351 #if 0/*!SEP_DRIVER_POLLING_MODE*/
3353 SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
3355 /* release IRQ line */
3356 free_irq(SEP_DIRVER_IRQ_NUM, &g_sep_reg_base_address);
3358 /* lock the sep mutex */
3359 mutex_unlock(&sep_mutex);
3362 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3363 "SEP Driver:<-------- sep_end_transaction_handler end\n");
3368 /* handler for flow done interrupt */
3369 static void sep_flow_done_handler(struct work_struct *work)
3371 /* flow context_ptr */
3372 struct sep_flow_context_t *flow_data_ptr;
3373 /*-------------------------
3375 ---------------------------*/
3377 /* obtain the mutex */
3378 mutex_lock(&sep_mutex);
3380 /* get the pointer to context */
3381 flow_data_ptr = (struct sep_flow_context_t *)work;
3383 /* free all the current input tables in sep */
3384 sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
3386 /* free all the current tables output tables in SEP (if needed) */
3387 if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
3388 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
3390 /* check if we have additional tables to be sent to SEP only input
3391 flag may be checked */
3392 if (flow_data_ptr->input_tables_flag) {
3393 /* copy the message to the shared RAM and signal SEP */
3394 memcpy((void *)flow_data_ptr->message,
3395 (void *)g_sep_shared_area_addr,
3396 flow_data_ptr->message_size_in_bytes);
3398 SEP_WRITE_REGISTER(g_sep_reg_base_address +
3399 HW_HOST_HOST_SEP_GPR2_REG_ADDR,
3402 mutex_unlock(&sep_mutex);
3407 This function creates a list of tables for flow and returns the data for
3408 the first and last tables of the list
3410 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
3411 unsigned long first_buff_addr,
3412 struct sep_flow_context_t *flow_data_ptr,
3413 struct sep_lli_entry_t *first_table_data_ptr,
3414 struct sep_lli_entry_t *last_table_data_ptr,
3415 bool isKernelVirtualAddress)
3420 /* virtaul address of one buffer */
3421 unsigned long virt_buff_addr;
3423 /* virtual size of one buffer */
3424 unsigned long virt_buff_size;
3426 /* table data for each created table */
3427 struct sep_lli_entry_t table_data;
3430 struct sep_lli_entry_t *info_entry_ptr;
3432 /* prevouis info entry */
3433 struct sep_lli_entry_t *prev_info_entry_ptr;
3438 /*-------------------------------
3440 ----------------------------------*/
3444 prev_info_entry_ptr = 0;
3446 /* init the first table to default */
3447 table_data.physical_address = 0xffffffff;
3448 first_table_data_ptr->physical_address = 0xffffffff;
3449 table_data.block_size = 0;
3451 for (i = 0; i < num_virtual_buffers; i++) {
3452 /* get the virtual buffer address */
3453 error = get_user(virt_buff_addr, &first_buff_addr);
3457 /* get the virtual buffer size */
3459 error = get_user(virt_buff_size, &first_buff_addr);
3463 /* advance the address to point to the next pair of address|size */
3466 /* now prepare the one flow LLI table from the data */
3467 error = sep_prepare_one_flow_dma_table(virt_buff_addr,
3472 isKernelVirtualAddress);
3477 /* if this is the first table - save it to return to the user
3479 *first_table_data_ptr = table_data;
3481 /* set the pointer to info entry */
3482 prev_info_entry_ptr = info_entry_ptr;
3484 /* not first table - the previous table info entry should
3486 prev_info_entry_ptr->block_size =
3487 (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
3488 (table_data.block_size);
3490 /* set the pointer to info entry */
3491 prev_info_entry_ptr = info_entry_ptr;
3495 /* set the last table data */
3496 *last_table_data_ptr = table_data;
3505 This function creates one DMA table for flow and returns its data,
3506 and pointer to its info entry
3508 static int sep_prepare_one_flow_dma_table(
3509 unsigned long virt_buff_addr,
3510 unsigned long virt_buff_size,
3511 struct sep_lli_entry_t *table_data,
3512 struct sep_lli_entry_t **info_entry_ptr,
3513 struct sep_flow_context_t *flow_data_ptr,
3514 bool isKernelVirtualAddress)
3519 /* the range in pages */
3520 unsigned long lli_array_size;
3522 /* array of pointers ot page */
3523 struct sep_lli_entry_t *lli_array;
3525 /* pointer to the entry in the dma table */
3526 struct sep_lli_entry_t *flow_dma_table_entry_ptr;
3528 /* address of the dma table */
3529 unsigned long *start_dma_table_ptr;
3531 /* total table data counter */
3532 unsigned long dma_table_data_count;
3534 /* pointer that will keep the pointer t the pages of the virtual buffer */
3535 struct page **page_array_ptr;
3538 unsigned long entry_count;
3540 /*-------------------------------
3542 ----------------------------------*/
3544 /* find the space for the new table */
3545 error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
3549 /* check if the pages are in Kernel Virtual Address layout */
3550 if (isKernelVirtualAddress == true)
3551 /* lock kernel buffer in the memory */
3552 error = sep_lock_kernel_pages(virt_buff_addr,
3558 /* lock user buffer in the memory */
3559 error = sep_lock_user_pages(virt_buff_addr,
3568 /* set the pointer to page array at the beginning of table - this table is
3569 now considered taken */
3570 *start_dma_table_ptr = lli_array_size;
3572 /* point to the place of the pages pointers of the table */
3573 start_dma_table_ptr++;
3575 /* set the pages pointer */
3576 *start_dma_table_ptr = (unsigned long)page_array_ptr;
3578 /* set the pointer to the first entry */
3579 flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
3581 /* now create the entries for table */
3582 for (dma_table_data_count = entry_count = 0;
3583 entry_count < lli_array_size;
3585 flow_dma_table_entry_ptr->physical_address =
3586 lli_array[entry_count].physical_address;
3588 flow_dma_table_entry_ptr->block_size =
3589 lli_array[entry_count].block_size;
3591 /* set the total data of a table */
3592 dma_table_data_count += lli_array[entry_count].block_size;
3594 flow_dma_table_entry_ptr++;
3597 /* set the physical address */
3598 table_data->physical_address = virt_to_phys(start_dma_table_ptr);
3600 /* set the num_entries and total data size */
3601 table_data->block_size = ((lli_array_size + 1) <<
3602 SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
3603 (dma_table_data_count);
3605 /* set the info entry */
3606 flow_dma_table_entry_ptr->physical_address = 0xffffffff;
3607 flow_dma_table_entry_ptr->block_size = 0;
3609 /* set the pointer to info entry */
3610 *info_entry_ptr = flow_dma_table_entry_ptr;
3612 /* the array of the lli entries */
3622 This function returns pointer to the flow data structure
3623 that conatins the given id
3625 static int sep_find_flow_context(
3626 unsigned long flow_id,
3627 struct sep_flow_context_t **flow_data_ptr)
3630 unsigned long count;
3635 /*-----------------------
3637 ---------------------------*/
3642 always search for flow with id default first - in case we
3643 already started working on the flow there can be no situation
3644 when 2 flows are with default flag
3646 for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
3647 if (g_sep_flows_data_array[count].flow_id == flow_id) {
3648 *flow_data_ptr = &g_sep_flows_data_array[count];
3653 if (count == SEP_DRIVER_NUM_FLOWS)
3661 this function find a space for the new flow dma table
3663 static int sep_find_free_flow_dma_table_space(
3664 unsigned long **table_address_ptr)
3669 /* pointer to the id field of the flow dma table */
3670 unsigned long *start_table_ptr;
3672 /* start address of the flow dma area */
3673 unsigned long flow_dma_area_start_addr;
3675 /* end address of the flow dma area */
3676 unsigned long flow_dma_area_end_addr;
3678 /* maximum table size in words */
3679 unsigned long table_size_in_words;
3681 /*---------------------
3683 -----------------------*/
3687 /* find the start address of the flow DMA table area */
3688 flow_dma_area_start_addr = g_sep_shared_area_addr +
3689 SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
3691 /* set end address of the flow table area */
3692 flow_dma_area_end_addr = flow_dma_area_start_addr +
3693 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
3695 /* set table size in words */
3696 table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
3697 (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
3699 /* set the pointer to the start address of DMA area */
3700 start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
3702 /* find the space for the next table */
3703 while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
3704 ((unsigned long)start_table_ptr <
3705 flow_dma_area_end_addr))
3706 start_table_ptr += table_size_in_words;
3708 /* check if we reached the end of floa tables area */
3709 if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
3712 *table_address_ptr = start_table_ptr;
3718 this function goes over all the flow tables connected to the given
3719 table and deallocate them
3721 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
3724 unsigned long *table_ptr;
3726 /* end address of the flow dma area */
3727 unsigned long num_entries;
3729 unsigned long num_pages;
3732 struct page **pages_ptr;
3734 /* maximum table size in words */
3735 struct sep_lli_entry_t *info_entry_ptr;
3737 /*-------------------------------
3739 ---------------------------------*/
3741 /* set the pointer to the first table */
3742 table_ptr = (unsigned long *)first_table_ptr->physical_address;
3744 /* set the num of entries */
3745 num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
3746 & SEP_NUM_ENTRIES_MASK;
3748 /* go over all the connected tables */
3749 while (*table_ptr != 0xffffffff) {
3750 /* get number of pages */
3751 num_pages = *(table_ptr - 2);
3753 /* get the pointer to the pages */
3754 pages_ptr = (struct page **)(*(table_ptr - 1));
3756 /* free the pages */
3757 sep_free_dma_pages(pages_ptr, num_pages, 1);
3759 /* goto to the info entry */
3760 info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
3763 table_ptr = (unsigned long *)info_entry_ptr->physical_address;
3764 num_entries = (info_entry_ptr->block_size >>
3765 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
3772 This function handler the set flow id command
3774 static int sep_set_flow_id_handler(unsigned long arg)
3780 unsigned long flow_id;
3782 /* pointer to flow data structre */
3783 struct sep_flow_context_t *flow_data_ptr;
3785 /*----------------------
3787 -----------------------*/
3789 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3790 "------------>SEP Driver: sep_set_flow_id_handler start\n");
3792 error = get_user(flow_id,
3793 &(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
3797 /* find the flow data structure that was just used for creating new flow
3798 - its id should be default */
3799 error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
3804 flow_data_ptr->flow_id = flow_id;
3808 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3809 "SEP Driver:<-------- sep_set_flow_id_handler end\n");
3817 calculates time and sets it at the predefined address
3819 static int sep_set_time(unsigned long *address_ptr,
3820 unsigned long *time_in_sec_ptr)
3823 struct timeval time;
3825 /* address of time in the kernel */
3826 unsigned long time_addr;
3829 /*------------------------
3831 --------------------------*/
3833 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3834 "SEP Driver:--------> sep_set_time start\n");
3837 do_gettimeofday(&time);
3839 /* set value in the SYSTEM MEMORY offset */
3840 time_addr = g_message_shared_area_addr +
3841 SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
3843 *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
3844 *(unsigned long *)(time_addr + 4) = time.tv_sec;
3846 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3847 "SEP Driver:time.tv_sec is %lu\n",
3849 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3850 "SEP Driver:time_addr is %lu\n",
3852 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3853 "SEP Driver:g_message_shared_area_addr is %lu\n",
3854 g_message_shared_area_addr);
3856 /* set the output parameters if needed */
3858 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
3860 if (time_in_sec_ptr)
3861 *time_in_sec_ptr = time.tv_sec;
3863 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3864 "SEP Driver:<-------- sep_set_time end\n");
3870 PATCH for configuring the DMA to single burst instead of multi-burst
3872 static void sep_configure_dma_burst(void)
3875 #define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL
3877 unsigned long regVal;
3879 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3880 "SEP Driver:<-------- sep_configure_dma_burst start \n");
3882 /* request access to registers from SEP */
3883 SEP_WRITE_REGISTER(g_sep_reg_base_address +
3884 HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2UL);
3886 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3887 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n");
3889 SEP_READ_REGISTER(g_sep_reg_base_address +
3890 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3892 SEP_READ_REGISTER(g_sep_reg_base_address +
3893 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3895 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3896 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n");
3898 /* set the DMA burst register to single burst*/
3899 SEP_WRITE_REGISTER(g_sep_reg_base_address +
3900 HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
3902 /* release the sep busy */
3903 SEP_WRITE_REGISTER(g_sep_reg_base_address +
3904 HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
3905 SEP_READ_REGISTER(g_sep_reg_base_address +
3906 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3907 while (regVal != 0x0)
3908 SEP_READ_REGISTER(g_sep_reg_base_address +
3909 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3911 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3912 "SEP Driver:<-------- sep_configure_dma_burst done \n");
3916 module_init(sep_init);
3917 module_exit(sep_exit);
3919 MODULE_LICENSE("GPL");