3 * sep_main_mod.c - Security Processor Driver main group of functions
5 * Copyright(c) 2009 Intel Corporation. All rights reserved.
6 * Copyright(c) 2009 Discretix. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Mark Allyn mark.a.allyn@intel.com
28 * 2009.06.26 Initial publish
32 #include <linux/init.h>
33 #include <linux/module.h>
35 #include <linux/cdev.h>
36 #include <linux/kdev_t.h>
37 #include <linux/mutex.h>
39 #include <linux/poll.h>
40 #include <linux/wait.h>
41 #include <asm/ioctl.h>
42 #include <linux/ioport.h>
44 #include <linux/interrupt.h>
45 #include <linux/pagemap.h>
46 #include <asm/cacheflush.h>
47 #include "sep_driver_hw_defs.h"
48 #include "sep_driver_config.h"
49 #include "sep_driver_api.h"
50 #include "sep_driver_ext_api.h"
53 /*----------------------------------------
55 -----------------------------------------*/
58 #define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
60 /*--------------------------------------
62 -----------------------------------------*/
66 /*--------------------------------------------
68 --------------------------------------------*/
70 /* debug messages level */
71 INT_MODULE_PARM(sepDebug, 0x0);
72 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
74 /* major and minor device numbers */
75 static dev_t g_sep_device_number;
77 /* the files operations structure of the driver */
78 static struct file_operations g_sep_fops;
80 /* cdev struct of the driver */
81 static struct cdev g_sep_cdev;
84 mutex for the access to the internals of the sep driver
86 static DEFINE_MUTEX(sep_mutex);
89 /* wait queue head (event) of the driver */
90 static DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
94 /*------------------------------------------------
96 ---------------------------------------------------*/
99 interrupt handler function
101 irqreturn_t sep_inthandler(int irq, void *dev_id);
104 this function registers the driver to the file system
106 static int sep_register_driver_to_fs(void);
109 this function unregisters driver from fs
111 static void sep_unregister_driver_from_fs(void);
114 this function calculates the size of data that can be inserted into the lli
115 table from this array the condition is that either the table is full
116 (all etnries are entered), or there are no more entries in the lli array
118 static unsigned long sep_calculate_lli_table_max_size(
119 struct sep_lli_entry_t *lli_in_array_ptr,
120 unsigned long num_array_entries);
122 this functions builds ont lli table from the lli_array according to the
125 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
126 struct sep_lli_entry_t *lli_table_ptr,
127 unsigned long *num_processed_entries_ptr,
128 unsigned long *num_table_entries_ptr,
129 unsigned long table_data_size);
132 this function goes over the list of the print created tables and prints
135 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
136 unsigned long num_table_entries,
137 unsigned long table_data_size);
142 This function raises interrupt to SEPm that signals that is has a new
145 static void sep_send_command_handler(void);
149 This function raises interrupt to SEP that signals that is has a
152 static void sep_send_reply_command_handler(void);
155 This function handles the allocate data pool memory request
156 This function returns calculates the physical address of the allocated memory
157 and the offset of this area from the mapped address. Therefore, the FVOs in
158 user space can calculate the exact virtual address of this allocated memory
160 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
164 This function handles write into allocated data pool command
166 static int sep_write_into_data_pool_handler(unsigned long arg);
169 this function handles the read from data pool command
171 static int sep_read_from_data_pool_handler(unsigned long arg);
174 this function handles tha request for creation of the DMA table
175 for the synchronic symmetric operations (AES,DES)
177 static int sep_create_sync_dma_tables_handler(unsigned long arg);
180 this function handles the request to create the DMA tables for flow
182 static int sep_create_flow_dma_tables_handler(unsigned long arg);
185 This API handles the end transaction request
187 static int sep_end_transaction_handler(unsigned long arg);
191 this function handles add tables to flow
193 static int sep_add_flow_tables_handler(unsigned long arg);
196 this function add the flow add message to the specific flow
198 static int sep_add_flow_tables_message_handler(unsigned long arg);
201 this function handles the request for SEP start
203 static int sep_start_handler(void);
206 this function handles the request for SEP initialization
208 static int sep_init_handler(unsigned long arg);
211 this function handles the request cache and resident reallocation
213 static int sep_realloc_cache_resident_handler(unsigned long arg);
217 This api handles the setting of API mode to blocking or non-blocking
219 static int sep_set_api_mode_handler(unsigned long arg);
221 /* handler for flow done interrupt */
222 static void sep_flow_done_handler(struct work_struct *work);
225 This function locks all the physical pages of the kernel virtual buffer
226 and construct a basic lli array, where each entry holds the physical
227 page address and the size that application data holds in this physical pages
229 static int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
230 unsigned long data_size,
231 unsigned long *num_pages_ptr,
232 struct sep_lli_entry_t **lli_array_ptr,
233 struct page ***page_array_ptr);
236 This function creates one DMA table for flow and returns its data,
237 and pointer to its info entry
239 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr,
240 unsigned long virt_buff_size,
241 struct sep_lli_entry_t *table_data,
242 struct sep_lli_entry_t **info_entry_ptr,
243 struct sep_flow_context_t *flow_data_ptr,
244 bool isKernelVirtualAddress);
247 This function creates a list of tables for flow and returns the data for the
248 first and last tables of the list
250 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
251 unsigned long first_buff_addr,
252 struct sep_flow_context_t *flow_data_ptr,
253 struct sep_lli_entry_t *first_table_data_ptr,
254 struct sep_lli_entry_t *last_table_data_ptr,
255 bool isKernelVirtualAddress);
258 this function find a space for the new flow dma table
260 static int sep_find_free_flow_dma_table_space(
261 unsigned long **table_address_ptr);
264 this function goes over all the flow tables connected to the given table and
267 static void sep_deallocated_flow_tables(
268 struct sep_lli_entry_t *first_table_ptr);
271 This function handler the set flow id command
273 static int sep_set_flow_id_handler(unsigned long arg);
276 This function returns pointer to the flow data structure
277 that conatins the given id
279 static int sep_find_flow_context(unsigned long flow_id,
280 struct sep_flow_context_t **flow_data_ptr);
284 this function returns the physical and virtual addresses of the static pool
286 static int sep_get_static_pool_addr_handler(unsigned long arg);
289 this address gets the offset of the physical address from the start of
292 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
296 this function handles the request for get time
298 static int sep_get_time_handler(unsigned long arg);
301 calculates time and sets it at the predefined address
303 static int sep_set_time(unsigned long *address_ptr,
304 unsigned long *time_in_sec_ptr);
307 PATCH for configuring the DMA to single burst instead of multi-burst
309 static void sep_configure_dma_burst(void);
312 This function locks all the physical pages of the
313 application virtual buffer and construct a basic lli
314 array, where each entry holds the physical page address
315 and the size that application data holds in this physical pages
317 static int sep_lock_user_pages(unsigned long app_virt_addr,
318 unsigned long data_size,
319 unsigned long *num_pages_ptr,
320 struct sep_lli_entry_t **lli_array_ptr,
321 struct page ***page_array_ptr);
323 /*---------------------------------------------
325 -----------------------------------------------*/
328 this function locks SEP by locking the semaphore
332 mutex_lock(&sep_mutex);
338 this function unlocks SEP
343 mutex_unlock(&sep_mutex);
347 this function returns the address of the message shared area
349 void sep_map_shared_area(unsigned long *mappedAddr_ptr)
351 *mappedAddr_ptr = sep_dev->shared_area_addr;
355 this function returns the address of the message shared area
357 void sep_send_msg_rdy_cmd()
359 sep_send_command_handler();
362 /* this functions frees all the resources that were allocated for the building
363 of the LLI DMA tables */
364 void sep_free_dma_resources()
366 sep_free_dma_table_data_handler();
369 /* poll(suspend), until reply from sep */
370 void sep_driver_poll()
372 unsigned long retVal = 0;
374 #ifdef SEP_DRIVER_POLLING_MODE
376 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
377 SEP_READ_REGISTER(sep_dev->reg_base_address +
378 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
381 sep_dev->sep_to_host_reply_counter++;
383 /* poll, until reply from sep */
384 wait_event(g_sep_event,
385 (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
390 /*----------------------------------------------------------------------
391 open function of the character driver - must only lock the mutex
392 must also release the memory data pool allocations
393 ------------------------------------------------------------------------*/
394 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
401 ---------------------*/
403 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> open start\n");
407 /* check the blocking mode */
408 if (sep_dev->block_mode_flag)
410 mutex_lock(&sep_mutex);
412 error = mutex_trylock(&sep_mutex);
414 /* check the error */
416 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
417 "SEP Driver: down_interruptible failed\n");
422 /* release data pool allocations */
423 sep_dev->data_pool_bytes_allocated = 0;
427 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- open end\n");
435 /*------------------------------------------------------------
437 -------------------------------------------------------------*/
438 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
442 ---------------------*/
444 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
445 "----------->SEP Driver: sep_release start\n");
447 #if 0/*!SEP_DRIVER_POLLING_MODE*/
449 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
451 /* release IRQ line */
452 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
456 /* unlock the sep mutex */
457 mutex_unlock(&sep_mutex);
459 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
460 "SEP Driver:<-------- sep_release end\n");
468 /*---------------------------------------------------------------
469 map function - this functions maps the message shared area
470 -----------------------------------------------------------------*/
471 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
474 unsigned long phys_addr;
476 /*-----------------------
478 -------------------------*/
480 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "-------->SEP Driver: mmap start\n");
482 /* check that the size of the mapped range is as the size of the message
484 if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
485 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
486 "SEP Driver mmap requested size is more than allowed\n");
487 printk(KERN_WARNING "SEP Driver mmap requested size is more \
489 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
491 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
496 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
497 "SEP Driver:g_message_shared_area_addr is %08lx\n",
498 sep_dev->message_shared_area_addr);
500 /* get physical address */
501 phys_addr = sep_dev->phys_shared_area_addr;
503 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: phys_addr is %08lx\n",
506 if (remap_pfn_range(vma,
508 phys_addr >> PAGE_SHIFT,
509 vma->vm_end - vma->vm_start,
510 vma->vm_page_prot)) {
511 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
512 "SEP Driver remap_page_range failed\n");
513 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
517 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- mmap end\n");
523 /*-----------------------------------------------
525 *----------------------------------------------*/
526 static unsigned int sep_poll(struct file *filp, poll_table *wait)
530 unsigned int mask = 0;
533 unsigned long retVal = 0;
535 /*----------------------------------------------
537 -------------------------------------------------*/
539 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "---------->SEP Driver poll: start\n");
542 #if SEP_DRIVER_POLLING_MODE
544 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
545 SEP_READ_REGISTER(sep_dev->reg_base_address +
546 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
549 for (count = 0; count < 10 * 4; count += 4)
550 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
551 "Poll Debug Word %lu of the message is %lu\n",
553 *((unsigned long *)(sep_dev->shared_area_addr +
554 SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
557 sep_dev->sep_to_host_reply_counter++;
559 /* add the event to the polling wait table */
560 poll_wait(filp, &g_sep_event, wait);
564 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
565 "sep_dev->host_to_sep_send_counter is %lu\n",
566 sep_dev->host_to_sep_send_counter);
567 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
568 "sep_dev->sep_to_host_reply_counter is %lu\n",
569 sep_dev->sep_to_host_reply_counter);
571 /* check if the data is ready */
572 if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
573 for (count = 0; count < 12 * 4; count += 4)
574 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
575 "Sep Mesg Word %lu of the message is %lu\n",
576 count, *((unsigned long *)(sep_dev->shared_area_addr + count)));
578 for (count = 0; count < 10 * 4; count += 4)
579 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
580 "Debug Data Word %lu of the message is %lu\n",
582 *((unsigned long *)(sep_dev->shared_area_addr + 0x1800 + count)));
584 SEP_READ_REGISTER(sep_dev->reg_base_address +
585 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
587 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "retVal is %lu\n", retVal);
588 /* check if the this is sep reply or request */
590 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
591 "SEP Driver: sep request in\n");
593 mask |= POLLOUT | POLLWRNORM;
595 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: sep reply in\n");
596 mask |= POLLIN | POLLRDNORM;
600 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- poll exit\n");
605 static int sep_ioctl(struct inode *inode,
614 /*------------------------
616 ------------------------*/
619 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
620 "------------>SEP Driver: ioctl start\n");
622 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: cmd is %x\n", cmd);
624 /* check that the command is for sep device */
625 if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
629 case SEP_IOCSENDSEPCOMMAND:
631 /* send command to SEP */
632 sep_send_command_handler();
634 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
635 "SEP Driver: after sep_send_command_handler\n");
639 case SEP_IOCSENDSEPRPLYCOMMAND:
641 /* send reply command to SEP */
642 sep_send_reply_command_handler();
646 case SEP_IOCALLOCDATAPOLL:
648 /* allocate data pool */
649 error = sep_allocate_data_pool_memory_handler(arg);
653 case SEP_IOCWRITEDATAPOLL:
655 /* write data into memory pool */
656 error = sep_write_into_data_pool_handler(arg);
660 case SEP_IOCREADDATAPOLL:
662 /* read data from data pool into application memory */
663 error = sep_read_from_data_pool_handler(arg);
667 case SEP_IOCCREATESYMDMATABLE:
669 /* create dma table for synhronic operation */
670 error = sep_create_sync_dma_tables_handler(arg);
674 case SEP_IOCCREATEFLOWDMATABLE:
676 /* create flow dma tables */
677 error = sep_create_flow_dma_tables_handler(arg);
681 case SEP_IOCFREEDMATABLEDATA:
684 error = sep_free_dma_table_data_handler();
688 case SEP_IOCSETFLOWID:
691 error = sep_set_flow_id_handler(arg);
695 case SEP_IOCADDFLOWTABLE:
697 /* add tables to the dynamic flow */
698 error = sep_add_flow_tables_handler(arg);
702 case SEP_IOCADDFLOWMESSAGE:
704 /* add message of add tables to flow */
705 error = sep_add_flow_tables_message_handler(arg);
709 case SEP_IOCSEPSTART:
711 /* start command to sep */
712 error = sep_start_handler();
717 /* init command to sep */
718 error = sep_init_handler(arg);
721 case SEP_IOCSETAPIMODE:
723 /* set non- blocking mode */
724 error = sep_set_api_mode_handler(arg);
728 case SEP_IOCGETSTATICPOOLADDR:
730 /* get the physical and virtual addresses of the static pool */
731 error = sep_get_static_pool_addr_handler(arg);
735 case SEP_IOCENDTRANSACTION:
737 error = sep_end_transaction_handler(arg);
741 case SEP_IOCREALLOCCACHERES:
743 error = sep_realloc_cache_resident_handler(arg);
747 case SEP_IOCGETMAPPEDADDROFFSET:
749 error = sep_get_physical_mapped_offset_handler(arg);
754 error = sep_get_time_handler(arg);
763 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
764 "SEP Driver:<-------- ioctl end\n");
771 this function registers the driver to the file system
773 static int sep_register_driver_to_fs(void)
778 /*---------------------
780 -----------------------*/
782 ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
784 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
785 "sep_driver:major number allocation failed, retval is %d\n", ret_val);
789 /* set the files operations structure */
790 g_sep_fops.owner = THIS_MODULE;
791 g_sep_fops.ioctl = sep_ioctl;
792 g_sep_fops.poll = sep_poll;
793 g_sep_fops.open = sep_open;
794 g_sep_fops.release = sep_release;
795 g_sep_fops.mmap = sep_mmap;
798 cdev_init(&g_sep_cdev, &g_sep_fops);
799 g_sep_cdev.owner = THIS_MODULE;
801 /* register the driver with the kernel */
802 ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
805 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
806 "sep_driver:cdev_add failed, retval is %d\n",
808 goto end_function_unregister_devnum;
813 end_function_unregister_devnum:
815 /* unregister dev numbers */
816 unregister_chrdev_region(g_sep_device_number, 1);
824 this function unregisters driver from fs
826 static void sep_unregister_driver_from_fs(void)
828 /*-------------------
830 ---------------------*/
832 cdev_del(&g_sep_cdev);
834 /* unregister dev numbers */
835 unregister_chrdev_region(g_sep_device_number, 1);
838 /*--------------------------------------------------------------
840 ----------------------------------------------------------------*/
841 static int __init sep_init(void)
849 /* size to of memory for allocation */
852 /*------------------------
854 ------------------------*/
856 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
857 "SEP Driver:-------->Init start\n");
858 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
859 "g_sep_shared_area_addr = %lx\n",
860 (unsigned long)&sep_dev->shared_area_addr);
864 /* transaction counter that coordinates the transactions between SEP
866 sep_dev->host_to_sep_send_counter = 0;
868 /* counter for the messages from sep */
869 sep_dev->sep_to_host_reply_counter = 0;
871 /* counter for the number of bytes allocated in the pool
872 for the current transaction */
873 sep_dev->data_pool_bytes_allocated = 0;
875 /* set the starting mode to blocking */
876 sep_dev->block_mode_flag = 1;
879 ret_val = sep_register_driver_to_device();
881 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
882 "sep_driver:sep_driver_to_device failed, ret_val is %d\n",
884 goto end_function_unregister_from_fs;
887 /* calculate the total size for allocation */
888 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
889 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
890 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
891 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
892 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
893 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
897 /* allocate the shared area */
898 if (sep_map_and_alloc_shared_area(size,
899 &sep_dev->shared_area_addr,
900 &sep_dev->phys_shared_area_addr)) {
902 /* allocation failed */
903 goto end_function_unmap_io_memory;
906 /* now set the memory regions */
907 sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
909 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
910 "SEP Driver: g_message_shared_area_addr is %08lx\n",
911 sep_dev->message_shared_area_addr);
913 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
915 /* send the new SHARED MESSAGE AREA to the SEP */
916 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_HOST_SEP_GPR1_REG_ADDR,
917 sep_dev->phys_shared_area_addr);
919 /* poll for SEP response */
920 SEP_READ_REGISTER(sep_dev->reg_base_address + HW_HOST_SEP_HOST_GPR1_REG_ADDR,
922 while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
923 SEP_READ_REGISTER(sep_dev->reg_base_address +
924 HW_HOST_SEP_HOST_GPR1_REG_ADDR,
927 /* check the return value (register) */
928 if (retVal != sep_dev->phys_shared_area_addr) {
930 goto end_function_deallocate_message_area;
935 /* init the flow contextes */
936 for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
937 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
939 sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
940 if (sep_dev->flow_wq_ptr == 0) {
942 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
943 "sep_driver:flow queue creation failed\n");
944 goto end_function_deallocate_sep_shared_area;
947 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
948 "SEP Driver: create flow workqueue \n");
950 /* register driver to fs */
951 ret_val = sep_register_driver_to_fs();
953 goto end_function_deallocate_sep_shared_area;
955 /* load the rom code */
960 end_function_unregister_from_fs:
962 /* unregister from fs */
963 sep_unregister_driver_from_fs();
965 end_function_deallocate_sep_shared_area:
967 /* de-allocate shared area */
968 sep_unmap_and_free_shared_area(size,
969 sep_dev->shared_area_addr,
970 sep_dev->phys_shared_area_addr);
972 end_function_unmap_io_memory:
974 iounmap((void *)sep_dev->reg_base_address);
976 /* release io memory region */
977 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
981 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- Init end\n");
989 /*-------------------------------------------------------------
991 --------------------------------------------------------------*/
992 static void __exit sep_exit(void)
997 /*-----------------------------
999 --------------------------------*/
1001 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> Exit start\n");
1003 /* unregister from fs */
1004 sep_unregister_driver_from_fs();
1006 /* calculate the total size for de-allocation */
1007 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
1008 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
1009 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
1010 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
1011 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
1012 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
1015 /* free shared area */
1016 sep_unmap_and_free_shared_area(size,
1017 sep_dev->shared_area_addr,
1018 sep_dev->phys_shared_area_addr);
1020 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1021 "SEP Driver: free pages SEP SHARED AREA \n");
1023 iounmap((void *)sep_dev->reg_base_address);
1025 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: iounmap \n");
1027 /* release io memory region */
1028 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1030 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: release_mem_region \n");
1032 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- Exit end\n");
1037 interrupt handler function
1039 irqreturn_t sep_inthandler(int irq, void *dev_id)
1042 irqreturn_t int_error;
1045 unsigned long error;
1048 unsigned long reg_val;
1051 unsigned long flow_id;
1054 struct sep_flow_context_t *flow_context_ptr;
1056 /*-----------------------------
1058 -----------------------------*/
1060 int_error = IRQ_HANDLED;
1062 /* read the IRR register to check if this is SEP interrupt */
1063 SEP_READ_REGISTER(sep_dev->reg_base_address + HW_HOST_IRR_REG_ADDR, reg_val);
1064 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Interrupt - reg is %08lx\n",
1067 /* check if this is the flow interrupt */
1068 if (0/*reg_val & (0x1 << 11)*/) {
1069 /* read GPRO to find out the which flow is done */
1070 SEP_READ_REGISTER(sep_dev->reg_base_address + HW_HOST_IRR_REG_ADDR,
1073 /* find the contex of the flow */
1074 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
1076 goto end_function_with_error;
1078 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
1080 /* queue the work */
1081 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
1084 /* check if this is reply interrupt from SEP */
1085 if (reg_val & (0x1 << 13)) {
1086 /* update the counter of reply messages */
1087 sep_dev->sep_to_host_reply_counter++;
1089 /* wake up the waiting process */
1090 wake_up(&g_sep_event);
1092 int_error = IRQ_NONE;
1097 end_function_with_error:
1099 /* clear the interrupt */
1100 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_ICR_REG_ADDR, reg_val);
1109 This function prepares only input DMA table for synhronic symmetric
1112 int sep_prepare_input_dma_table(unsigned long app_virt_addr,
1113 unsigned long data_size,
1114 unsigned long block_size,
1115 unsigned long *lli_table_ptr,
1116 unsigned long *num_entries_ptr,
1117 unsigned long *table_data_size_ptr,
1118 bool isKernelVirtualAddress)
1121 /* pointer to the info entry of the table - the last entry */
1122 struct sep_lli_entry_t *info_entry_ptr;
1124 /* array of pointers ot page */
1125 struct sep_lli_entry_t *lli_array_ptr;
1127 /* points to the first entry to be processed in the lli_in_array */
1128 unsigned long current_entry;
1130 /* num entries in the virtual buffer */
1131 unsigned long sep_lli_entries;
1133 /* lli table pointer */
1134 struct sep_lli_entry_t *in_lli_table_ptr;
1136 /* the total data in one table */
1137 unsigned long table_data_size;
1139 /* number of entries in lli table */
1140 unsigned long num_entries_in_table;
1142 /* next table address */
1143 unsigned long lli_table_alloc_addr;
1146 unsigned long result;
1148 /*------------------------
1150 --------------------------*/
1152 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1153 "SEP Driver:--------> sep_prepare_input_dma_table start\n");
1155 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:data_size is %lu\n",
1157 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:block_size is %lu\n",
1160 /* initialize the pages pointers */
1161 sep_dev->in_page_array = 0;
1162 sep_dev->in_num_pages = 0;
1164 if (data_size == 0) {
1165 /* special case - created 2 entries table with zero data */
1166 in_lli_table_ptr = (struct sep_lli_entry_t *)(sep_dev->shared_area_addr +
1167 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1168 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr +
1169 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1170 in_lli_table_ptr->block_size = 0;
1173 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1174 in_lli_table_ptr->block_size = 0;
1176 *lli_table_ptr = sep_dev->phys_shared_area_addr +
1177 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1178 *num_entries_ptr = 2;
1179 *table_data_size_ptr = 0;
1184 /* check if the pages are in Kernel Virtual Address layout */
1185 if (isKernelVirtualAddress == true)
1186 /* lock the pages of the kernel buffer and translate them to pages */
1187 result = sep_lock_kernel_pages(app_virt_addr,
1189 &sep_dev->in_num_pages,
1191 &sep_dev->in_page_array);
1193 /* lock the pages of the user buffer and translate them to pages */
1194 result = sep_lock_user_pages(app_virt_addr,
1196 &sep_dev->in_num_pages,
1198 &sep_dev->in_page_array);
1203 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1204 "SEP Driver:output sep_dev->in_num_pages is %lu\n",
1205 sep_dev->in_num_pages);
1209 sep_lli_entries = sep_dev->in_num_pages;
1211 /* initiate to point after the message area */
1212 lli_table_alloc_addr = sep_dev->shared_area_addr +
1213 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1215 /* loop till all the entries in in array are not processed */
1216 while (current_entry < sep_lli_entries) {
1217 /* set the new input and output tables */
1218 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1220 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1221 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1223 /* calculate the maximum size of data for input table */
1224 table_data_size = sep_calculate_lli_table_max_size(
1225 &lli_array_ptr[current_entry],
1226 (sep_lli_entries - current_entry));
1228 /* now calculate the table size so that it will be module block size */
1229 table_data_size = (table_data_size / block_size) * block_size;
1231 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1232 "SEP Driver:output table_data_size is %lu\n",
1235 /* construct input lli table */
1236 sep_build_lli_table(&lli_array_ptr[current_entry],
1239 &num_entries_in_table,
1242 if (info_entry_ptr == 0) {
1243 /* set the output parameters to physical addresses */
1244 *lli_table_ptr = sep_shared_area_virt_to_phys(
1245 (unsigned long)in_lli_table_ptr);
1246 *num_entries_ptr = num_entries_in_table;
1247 *table_data_size_ptr = table_data_size;
1249 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1250 "SEP Driver:output lli_table_in_ptr is %08lx\n",
1253 /* update the info entry of the previous in table */
1254 info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
1255 (unsigned long)in_lli_table_ptr);
1256 info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
1260 /* save the pointer to the info entry of the current tables */
1261 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1264 /* print input tables */
1265 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1266 sep_shared_area_phys_to_virt(*lli_table_ptr),
1268 *table_data_size_ptr);
1270 /* the array of the pages */
1271 kfree(lli_array_ptr);
1275 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1276 "SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1283 This function builds input and output DMA tables for synhronic
1284 symmetric operations (AES, DES). It also checks that each table
1285 is of the modular block size
1287 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
1288 unsigned long app_virt_out_addr,
1289 unsigned long data_size,
1290 unsigned long block_size,
1291 unsigned long *lli_table_in_ptr,
1292 unsigned long *lli_table_out_ptr,
1293 unsigned long *in_num_entries_ptr,
1294 unsigned long *out_num_entries_ptr,
1295 unsigned long *table_data_size_ptr,
1296 bool isKernelVirtualAddress)
1299 /* array of pointers of page */
1300 struct sep_lli_entry_t *lli_in_array;
1302 /* array of pointers of page */
1303 struct sep_lli_entry_t *lli_out_array;
1309 /*------------------------
1311 --------------------------*/
1313 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1314 "SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1318 /* initialize the pages pointers */
1319 sep_dev->in_page_array = 0;
1320 sep_dev->out_page_array = 0;
1322 /* check if the pages are in Kernel Virtual Address layout */
1323 if (isKernelVirtualAddress == true) {
1324 /* lock the pages of the kernel buffer and translate them to pages */
1325 result = sep_lock_kernel_pages(app_virt_in_addr,
1327 &sep_dev->in_num_pages,
1329 &sep_dev->in_page_array);
1331 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1332 "SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1336 /* lock the pages of the user buffer and translate them to pages */
1337 result = sep_lock_user_pages(app_virt_in_addr,
1339 &sep_dev->in_num_pages,
1341 &sep_dev->in_page_array);
1343 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1344 "SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1349 if (isKernelVirtualAddress == true) {
1350 result = sep_lock_kernel_pages(app_virt_out_addr,
1352 &sep_dev->out_num_pages,
1354 &sep_dev->out_page_array);
1356 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1357 "SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1358 goto end_function_with_error1;
1361 result = sep_lock_user_pages(app_virt_out_addr,
1363 &sep_dev->out_num_pages,
1365 &sep_dev->out_page_array);
1367 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1368 "SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1369 goto end_function_with_error1;
1374 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1375 "sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1376 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1377 "sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1378 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1379 "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
1380 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1383 /* call the fucntion that creates table from the lli arrays */
1384 result = sep_construct_dma_tables_from_lli(lli_in_array,
1385 sep_dev->in_num_pages,
1387 sep_dev->out_num_pages,
1392 out_num_entries_ptr,
1393 table_data_size_ptr);
1395 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1396 "SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1397 goto end_function_with_error2;
1400 /* fall through - free the lli entry arrays */
1402 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "in_num_entries_ptr is %08lx\n",
1403 *in_num_entries_ptr);
1404 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "out_num_entries_ptr is %08lx\n",
1405 *out_num_entries_ptr);
1406 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "table_data_size_ptr is %08lx\n",
1407 *table_data_size_ptr);
1410 end_function_with_error2:
1412 kfree(lli_out_array);
1414 end_function_with_error1:
1416 kfree(lli_in_array);
1420 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1421 "SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n",
1430 This function creates the input and output dma tables for
1431 symmetric operations (AES/DES) according to the block size from LLI arays
1433 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
1434 unsigned long sep_in_lli_entries,
1435 struct sep_lli_entry_t *lli_out_array,
1436 unsigned long sep_out_lli_entries,
1437 unsigned long block_size,
1438 unsigned long *lli_table_in_ptr,
1439 unsigned long *lli_table_out_ptr,
1440 unsigned long *in_num_entries_ptr,
1441 unsigned long *out_num_entries_ptr,
1442 unsigned long *table_data_size_ptr)
1444 /* points to the area where next lli table can be allocated */
1445 unsigned long lli_table_alloc_addr;
1447 /* input lli table */
1448 struct sep_lli_entry_t *in_lli_table_ptr;
1450 /* output lli table */
1451 struct sep_lli_entry_t *out_lli_table_ptr;
1453 /* pointer to the info entry of the table - the last entry */
1454 struct sep_lli_entry_t *info_in_entry_ptr;
1456 /* pointer to the info entry of the table - the last entry */
1457 struct sep_lli_entry_t *info_out_entry_ptr;
1459 /* points to the first entry to be processed in the lli_in_array */
1460 unsigned long current_in_entry;
1462 /* points to the first entry to be processed in the lli_out_array */
1463 unsigned long current_out_entry;
1465 /* max size of the input table */
1466 unsigned long in_table_data_size;
1468 /* max size of the output table */
1469 unsigned long out_table_data_size;
1471 /* flag te signifies if this is the first tables build from the arrays */
1472 unsigned long first_table_flag;
1474 /* the data size that should be in table */
1475 unsigned long table_data_size;
1477 /* number of etnries in the input table */
1478 unsigned long num_entries_in_table;
1480 /* number of etnries in the output table */
1481 unsigned long num_entries_out_table;
1483 /*---------------------
1485 ------------------------*/
1487 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1488 "SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1490 /* initiate to pint after the message area */
1491 lli_table_alloc_addr = sep_dev->shared_area_addr +
1492 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1494 current_in_entry = 0;
1495 current_out_entry = 0;
1496 first_table_flag = 1;
1497 info_in_entry_ptr = 0;
1498 info_out_entry_ptr = 0;
1500 /* loop till all the entries in in array are not processed */
1501 while (current_in_entry < sep_in_lli_entries) {
1502 /* set the new input and output tables */
1503 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1505 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1506 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1508 /* set the first output tables */
1509 out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1511 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1512 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1514 /* calculate the maximum size of data for input table */
1515 in_table_data_size =
1516 sep_calculate_lli_table_max_size(
1517 &lli_in_array[current_in_entry],
1518 (sep_in_lli_entries - current_in_entry));
1520 /* calculate the maximum size of data for output table */
1521 out_table_data_size =
1522 sep_calculate_lli_table_max_size(
1523 &lli_out_array[current_out_entry],
1524 (sep_out_lli_entries - current_out_entry));
1526 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1527 "SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1528 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1529 "SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1531 /* check where the data is smallest */
1532 table_data_size = in_table_data_size;
1533 if (table_data_size > out_table_data_size)
1534 table_data_size = out_table_data_size;
1536 /* now calculate the table size so that it will be module block size */
1537 table_data_size = (table_data_size / block_size) * block_size;
1539 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1540 "SEP Driver:table_data_size is %lu\n",
1543 /* construct input lli table */
1544 sep_build_lli_table(&lli_in_array[current_in_entry],
1547 &num_entries_in_table,
1550 /* construct output lli table */
1551 sep_build_lli_table(&lli_out_array[current_out_entry],
1554 &num_entries_out_table,
1557 /* if info entry is null - this is the first table built */
1558 if (info_in_entry_ptr == 0) {
1559 /* set the output parameters to physical addresses */
1561 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1562 *in_num_entries_ptr = num_entries_in_table;
1563 *lli_table_out_ptr =
1564 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1565 *out_num_entries_ptr = num_entries_out_table;
1566 *table_data_size_ptr = table_data_size;
1568 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1569 "SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1570 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1571 "SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1573 /* update the info entry of the previous in table */
1574 info_in_entry_ptr->physical_address =
1575 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1576 info_in_entry_ptr->block_size =
1577 ((num_entries_in_table) << 24) | (table_data_size);
1579 /* update the info entry of the previous in table */
1580 info_out_entry_ptr->physical_address =
1581 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1582 info_out_entry_ptr->block_size =
1583 ((num_entries_out_table) << 24) | (table_data_size);
1586 /* save the pointer to the info entry of the current tables */
1587 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1588 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1590 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1591 "SEP Driver:output num_entries_out_table is %lu\n",
1592 (unsigned long)num_entries_out_table);
1593 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1594 "SEP Driver:output info_in_entry_ptr is %lu\n",
1595 (unsigned long)info_in_entry_ptr);
1596 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1597 "SEP Driver:output info_out_entry_ptr is %lu\n",
1598 (unsigned long)info_out_entry_ptr);
1601 /* print input tables */
1602 sep_debug_print_lli_tables(
1603 (struct sep_lli_entry_t *)
1604 sep_shared_area_phys_to_virt(*lli_table_in_ptr),
1605 *in_num_entries_ptr,
1606 *table_data_size_ptr);
1608 /* print output tables */
1609 sep_debug_print_lli_tables(
1610 (struct sep_lli_entry_t *)
1611 sep_shared_area_phys_to_virt(*lli_table_out_ptr),
1612 *out_num_entries_ptr,
1613 *table_data_size_ptr);
1615 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1616 "SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1622 this function calculates the size of data that can be inserted into the lli
1623 table from this array the condition is that either the table is full
1624 (all etnries are entered), or there are no more entries in the lli array
1626 unsigned long sep_calculate_lli_table_max_size(
1627 struct sep_lli_entry_t *lli_in_array_ptr,
1628 unsigned long num_array_entries)
1630 /* table data size */
1631 unsigned long table_data_size;
1634 unsigned long counter;
1636 /*---------------------
1638 ----------------------*/
1640 table_data_size = 0;
1642 /* calculate the data in the out lli table if till we fill the whole
1643 table or till the data has ended */
1645 (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
1646 (counter < num_array_entries); counter++)
1647 table_data_size += lli_in_array_ptr[counter].block_size;
1649 return table_data_size;
1653 this functions builds ont lli table from the lli_array according to
1654 the given size of data
1656 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
1657 struct sep_lli_entry_t *lli_table_ptr,
1658 unsigned long *num_processed_entries_ptr,
1659 unsigned long *num_table_entries_ptr,
1660 unsigned long table_data_size)
1662 /* current table data size */
1663 unsigned long curr_table_data_size;
1665 /* counter of lli array entry */
1666 unsigned long array_counter;
1668 /*-----------------------
1670 ---------------------------*/
1672 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1673 "SEP Driver:--------> sep_build_lli_table start\n");
1675 /* init currrent table data size and lli array entry counter */
1676 curr_table_data_size = 0;
1678 *num_table_entries_ptr = 1;
1680 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1681 "SEP Driver:table_data_size is %lu\n",
1684 /* fill the table till table size reaches the needed amount */
1685 while (curr_table_data_size < table_data_size) {
1686 /* update the number of entries in table */
1687 (*num_table_entries_ptr)++;
1689 lli_table_ptr->physical_address =
1690 lli_array_ptr[array_counter].physical_address;
1691 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1692 curr_table_data_size += lli_table_ptr->block_size;
1694 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1695 "SEP Driver:lli_table_ptr is %08lx\n",
1696 (unsigned long)lli_table_ptr);
1697 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1698 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1699 lli_table_ptr->physical_address);
1700 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1701 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1702 lli_table_ptr->block_size);
1704 /* check for overflow of the table data */
1705 if (curr_table_data_size > table_data_size) {
1706 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1707 "SEP Driver:curr_table_data_size > table_data_size\n");
1709 /* update the size of block in the table */
1710 lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1712 /* update the physical address in the lli array */
1713 lli_array_ptr[array_counter].physical_address +=
1714 lli_table_ptr->block_size;
1716 /* update the block size left in the lli array */
1717 lli_array_ptr[array_counter].block_size =
1718 (curr_table_data_size - table_data_size);
1720 /* advance to the next entry in the lli_array */
1723 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1724 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1725 lli_table_ptr->physical_address);
1726 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1727 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1728 lli_table_ptr->block_size);
1730 /* move to the next entry in table */
1734 /* set the info entry to default */
1735 lli_table_ptr->physical_address = 0xffffffff;
1736 lli_table_ptr->block_size = 0;
1738 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1739 "SEP Driver:lli_table_ptr is %08lx\n",
1740 (unsigned long)lli_table_ptr);
1741 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1742 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1743 lli_table_ptr->physical_address);
1744 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1745 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1746 lli_table_ptr->block_size);
1749 /* set the output parameter */
1750 *num_processed_entries_ptr += array_counter;
1752 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1753 "SEP Driver:*num_processed_entries_ptr is %lu\n",
1754 *num_processed_entries_ptr);
1757 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1758 "SEP Driver:<-------- sep_build_lli_table end\n");
1764 this function goes over the list of the print created tables and
1767 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
1768 unsigned long num_table_entries,
1769 unsigned long table_data_size)
1771 unsigned long table_count;
1773 unsigned long entries_count;
1774 /*-----------------------------
1776 -------------------------------*/
1778 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1779 "SEP Driver:--------> sep_debug_print_lli_tables start\n");
1782 while ((unsigned long)lli_table_ptr != 0xffffffff) {
1783 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1784 "SEP Driver: lli table %08lx, table_data_size is %lu\n",
1787 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1788 "SEP Driver: num_table_entries is %lu\n", num_table_entries);
1790 /* print entries of the table (without info entry) */
1791 for (entries_count = 0;
1792 entries_count < num_table_entries;
1793 entries_count++, lli_table_ptr++) {
1794 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1795 "SEP Driver:lli_table_ptr address is %08lx\n",
1796 (unsigned long)lli_table_ptr);
1797 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1798 "SEP Driver:phys address is %08lx block size is %lu\n",
1799 lli_table_ptr->physical_address, lli_table_ptr->block_size);
1802 /* point to the info entry */
1805 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1806 "SEP Driver:phys lli_table_ptr->block_size is %lu\n",
1807 lli_table_ptr->block_size);
1808 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1809 "SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
1810 lli_table_ptr->physical_address);
1813 table_data_size = lli_table_ptr->block_size & 0xffffff;
1814 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1815 lli_table_ptr = (struct sep_lli_entry_t *)
1816 (lli_table_ptr->physical_address);
1818 DEBUG_PRINT_3(SEP_DEBUG_LEVEL_EXTENDED,
1819 "SEP Driver:phys table_data_size is %lu num_table_entries is \
1820 %lu lli_table_ptr is%lu\n",
1821 table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
1823 if ((unsigned long)lli_table_ptr != 0xffffffff)
1824 lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
1825 (unsigned long)lli_table_ptr);
1830 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1831 "SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1836 This function locks all the physical pages of the application virtual buffer
1837 and construct a basic lli array, where each entry holds the physical page
1838 address and the size that application data holds in this physical pages
1840 int sep_lock_user_pages(unsigned long app_virt_addr,
1841 unsigned long data_size,
1842 unsigned long *num_pages_ptr,
1843 struct sep_lli_entry_t **lli_array_ptr,
1844 struct page ***page_array_ptr)
1850 /* the the page of the end address of the user space buffer */
1851 unsigned long end_page;
1853 /* the page of the start address of the user space buffer */
1854 unsigned long start_page;
1856 /* the range in pages */
1857 unsigned long num_pages;
1859 /* array of pointers ot page */
1860 struct page **page_array;
1863 struct sep_lli_entry_t *lli_array;
1866 unsigned long count;
1871 /*------------------------
1873 --------------------------*/
1875 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1876 "SEP Driver:--------> sep_lock_user_pages start\n");
1880 /* set start and end pages and num pages */
1881 end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1882 start_page = app_virt_addr >> PAGE_SHIFT;
1883 num_pages = end_page - start_page + 1;
1885 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1886 "SEP Driver: app_virt_addr is %08lx\n",
1888 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1889 "SEP Driver: data_size is %lu\n",
1891 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1892 "SEP Driver: start_page is %lu\n",
1894 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1895 "SEP Driver: end_page is %lu\n",
1897 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1898 "SEP Driver: num_pages is %lu\n",
1901 /* allocate array of pages structure pointers */
1902 page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1904 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1905 "SEP Driver: kmalloc for page_array failed\n");
1911 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1913 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1914 "SEP Driver: kmalloc for lli_array failed\n");
1917 goto end_function_with_error1;
1920 /* convert the application virtual address into a set of physical */
1921 down_read(¤t->mm->mmap_sem);
1922 result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
1925 up_read(¤t->mm->mmap_sem);
1927 /* check the number of pages locked - if not all then exit with error */
1928 if (result != num_pages) {
1929 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1930 "SEP Driver: not all pages locked by get_user_pages\n");
1933 goto end_function_with_error2;
1936 /* flush the cache */
1937 for (count = 0; count < num_pages; count++)
1938 flush_dcache_page(page_array[count]);
1940 /* set the start address of the first page - app data may start not at
1941 the beginning of the page */
1942 lli_array[0].physical_address = (
1943 (unsigned long)page_to_phys(page_array[0])) +
1944 (app_virt_addr & (~PAGE_MASK)) ;
1946 /* check that not all the data is in the first page only */
1947 if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1948 lli_array[0].block_size = data_size;
1950 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1953 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1954 "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
1955 lli_array[0].physical_address,
1956 lli_array[0].block_size);
1958 /* go from the second page to the prev before last */
1959 for (count = 1; count < (num_pages - 1); count++) {
1960 lli_array[count].physical_address =
1961 (unsigned long)page_to_phys(page_array[count]);
1962 lli_array[count].block_size = PAGE_SIZE;
1964 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1965 "lli_array[%lu].physical_address is %08lx, \
1966 lli_array[%lu].block_size is %lu\n",
1967 count, lli_array[count].physical_address,
1969 lli_array[count].block_size);
1972 /* if more then 1 pages locked - then update for the last page size needed */
1973 if (num_pages > 1) {
1974 /* update the address of the last page */
1975 lli_array[count].physical_address =
1976 (unsigned long)page_to_phys(page_array[count]);
1978 /* set the size of the last page */
1979 lli_array[count].block_size = (app_virt_addr + data_size) &
1982 if (lli_array[count].block_size == 0) {
1983 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1984 "app_virt_addr is %08lx\n",
1986 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
1989 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1990 "lli_array[%lu].physical_address is %08lx, \
1991 lli_array[%lu].block_size is %lu\n",
1992 count, lli_array[count].physical_address,
1994 lli_array[count].block_size);
1997 /* set output params */
1998 *lli_array_ptr = lli_array;
1999 *num_pages_ptr = num_pages;
2000 *page_array_ptr = page_array;
2004 end_function_with_error2:
2006 /* release the cache */
2007 for (count = 0; count < num_pages; count++)
2008 page_cache_release(page_array[count]);
2010 /* free lli array */
2013 end_function_with_error1:
2015 /* free page array */
2020 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2021 "SEP Driver:<-------- sep_lock_user_pages end\n");
2027 This function locks all the physical pages of the kernel virtual buffer
2028 and construct a basic lli array, where each entry holds the physical
2029 page address and the size that application data holds in this physical pages
2031 int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
2032 unsigned long data_size,
2033 unsigned long *num_pages_ptr,
2034 struct sep_lli_entry_t **lli_array_ptr,
2035 struct page ***page_array_ptr)
2041 /* the the page of the end address of the user space buffer */
2042 unsigned long end_page;
2044 /* the page of the start address of the user space buffer */
2045 unsigned long start_page;
2047 /* the range in pages */
2048 unsigned long num_pages;
2051 struct sep_lli_entry_t *lli_array;
2053 /* next kernel address to map */
2054 unsigned long next_kernel_address;
2057 unsigned long count;
2060 /*------------------------
2062 --------------------------*/
2064 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2065 "SEP Driver:--------> sep_lock_kernel_pages start\n");
2069 /* set start and end pages and num pages */
2070 end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
2071 start_page = kernel_virt_addr >> PAGE_SHIFT;
2072 num_pages = end_page - start_page + 1;
2074 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2075 "SEP Driver: kernel_virt_addr is %08lx\n",
2077 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2078 "SEP Driver: data_size is %lu\n",
2080 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2081 "SEP Driver: start_page is %lx\n",
2083 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2084 "SEP Driver: end_page is %lx\n",
2086 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2087 "SEP Driver: num_pages is %lu\n",
2090 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
2092 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
2093 "SEP Driver: kmalloc for lli_array failed\n");
2099 /* set the start address of the first page - app data may start not at
2100 the beginning of the page */
2101 lli_array[0].physical_address =
2102 (unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
2104 /* check that not all the data is in the first page only */
2105 if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
2106 lli_array[0].block_size = data_size;
2108 lli_array[0].block_size =
2109 PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
2112 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2113 "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
2114 lli_array[0].physical_address,
2115 lli_array[0].block_size);
2117 /* advance the address to the start of the next page */
2118 next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
2120 /* go from the second page to the prev before last */
2121 for (count = 1; count < (num_pages - 1); count++) {
2122 lli_array[count].physical_address =
2123 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2124 lli_array[count].block_size = PAGE_SIZE;
2126 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2127 "lli_array[%lu].physical_address is %08lx, \
2128 lli_array[%lu].block_size is %lu\n",
2129 count, lli_array[count].physical_address, count,
2130 lli_array[count].block_size);
2132 next_kernel_address += PAGE_SIZE;
2135 /* if more then 1 pages locked - then update for the last page size needed */
2136 if (num_pages > 1) {
2137 /* update the address of the last page */
2138 lli_array[count].physical_address =
2139 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2141 /* set the size of the last page */
2142 lli_array[count].block_size =
2143 (kernel_virt_addr + data_size) & (~PAGE_MASK);
2145 if (lli_array[count].block_size == 0) {
2146 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
2147 "app_virt_addr is %08lx\n",
2149 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
2153 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2154 "lli_array[%lu].physical_address is %08lx, \
2155 lli_array[%lu].block_size is %lu\n",
2156 count, lli_array[count].physical_address,
2158 lli_array[count].block_size);
2161 /* set output params */
2162 *lli_array_ptr = lli_array;
2163 *num_pages_ptr = num_pages;
2164 *page_array_ptr = 0;
2169 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2170 "SEP Driver:<-------- sep_lock_kernel_pages end\n");
2176 This function releases all the application virtual buffer physical pages,
2177 that were previously locked
2179 int sep_free_dma_pages(struct page **page_array_ptr,
2180 unsigned long num_pages,
2181 unsigned long dirtyFlag)
2184 unsigned long count;
2186 /*-------------------
2188 ---------------------*/
2191 for (count = 0; count < num_pages; count++) {
2192 /* the out array was written, therefore the data was changed */
2193 if (!PageReserved(page_array_ptr[count]))
2194 SetPageDirty(page_array_ptr[count]);
2195 page_cache_release(page_array_ptr[count]);
2198 /* free in pages - the data was only read, therefore no update was done
2200 for (count = 0; count < num_pages; count++)
2201 page_cache_release(page_array_ptr[count]);
2205 /* free the array */
2206 kfree(page_array_ptr);
2212 This function raises interrupt to SEP that signals that is has a new
2215 static void sep_send_command_handler()
2218 unsigned long count;
2220 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2221 "SEP Driver:--------> sep_send_command_handler start\n");
2228 for (count = 0; count < 12 * 4; count += 4)
2229 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2230 "Word %lu of the message is %lu\n",
2232 *((unsigned long *)(sep_dev->shared_area_addr + count)));
2234 /* update counter */
2235 sep_dev->host_to_sep_send_counter++;
2237 /* send interrupt to SEP */
2238 SEP_WRITE_REGISTER(sep_dev->reg_base_address +
2239 HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2241 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2242 "SEP Driver:<-------- sep_send_command_handler end\n");
2248 This function raises interrupt to SEPm that signals that is has a
2249 new command from HOST
2251 static void sep_send_reply_command_handler()
2253 unsigned long count;
2255 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2256 "SEP Driver:--------> sep_send_reply_command_handler start\n");
2261 for (count = 0; count < 12 * 4; count += 4)
2262 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2263 "Word %lu of the message is %lu\n",
2265 *((unsigned long *)(sep_dev->shared_area_addr + count)));
2268 /* update counter */
2269 sep_dev->host_to_sep_send_counter++;
2271 /* send the interrupt to SEP */
2272 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_HOST_SEP_GPR2_REG_ADDR,
2273 sep_dev->host_to_sep_send_counter);
2275 /* update both counters */
2276 sep_dev->host_to_sep_send_counter++;
2278 sep_dev->sep_to_host_reply_counter++;
2280 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2281 "SEP Driver:<-------- sep_send_reply_command_handler end\n");
2289 This function handles the allocate data pool memory request
2290 This function returns calculates the physical address of the
2291 allocated memory, and the offset of this area from the mapped address.
2292 Therefore, the FVOs in user space can calculate the exact virtual
2293 address of this allocated memory
2295 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
2300 /* command paramaters */
2301 struct sep_driver_alloc_t command_args;
2303 /*-------------------------
2305 ----------------------------*/
2307 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2308 "SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
2311 error = copy_from_user(&command_args,
2313 sizeof(struct sep_driver_alloc_t));
2317 /* allocate memory */
2319 (sep_dev->data_pool_bytes_allocated + command_args.num_bytes) >
2320 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
2325 /* set the virtual and physical address */
2326 command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2327 sep_dev->data_pool_bytes_allocated;
2328 command_args.phys_address = sep_dev->phys_shared_area_addr +
2329 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2330 sep_dev->data_pool_bytes_allocated;
2332 /* write the memory back to the user space */
2333 error = copy_to_user((void *)arg,
2334 (void *)&command_args,
2335 sizeof(struct sep_driver_alloc_t));
2339 /* set the allocation */
2340 sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
2344 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2345 "SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
2351 This function handles write into allocated data pool command
2353 static int sep_write_into_data_pool_handler(unsigned long arg)
2358 /* virtual address */
2359 unsigned long virt_address;
2361 /* application in address */
2362 unsigned long app_in_address;
2364 /* number of bytes */
2365 unsigned long num_bytes;
2367 /* address of the data pool */
2368 unsigned long data_pool_area_addr;
2370 /*--------------------------
2372 -----------------------------*/
2374 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2375 "SEP Driver:--------> sep_write_into_data_pool_handler start\n");
2377 /* get the application address */
2378 error = get_user(app_in_address,
2379 &(((struct sep_driver_write_t *)arg)->app_address));
2383 /* get the virtual kernel address address */
2384 error = get_user(virt_address,
2385 &(((struct sep_driver_write_t *)arg)->datapool_address));
2389 /* get the number of bytes */
2390 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2394 /* calculate the start of the data pool */
2395 data_pool_area_addr = sep_dev->shared_area_addr +
2396 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2399 /* check that the range of the virtual kernel address is correct */
2400 if ((virt_address < data_pool_area_addr) ||
2401 (virt_address > (data_pool_area_addr +
2402 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2407 /* copy the application data */
2408 error = copy_from_user((void *)virt_address,
2409 (void *)app_in_address,
2414 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2415 "SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
2421 this function handles the read from data pool command
2423 static int sep_read_from_data_pool_handler(unsigned long arg)
2428 /* virtual address of dest application buffer */
2429 unsigned long app_out_address;
2431 /* virtual address of the data pool */
2432 unsigned long virt_address;
2435 unsigned long num_bytes;
2437 /* address of the data pool */
2438 unsigned long data_pool_area_addr;
2440 /*------------------------
2442 -----------------------------*/
2444 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2445 "SEP Driver:--------> sep_read_from_data_pool_handler start\n");
2447 /* get the application address */
2448 error = get_user(app_out_address,
2449 &(((struct sep_driver_write_t *)arg)->app_address));
2453 /* get the virtual kernel address address */
2454 error = get_user(virt_address,
2455 &(((struct sep_driver_write_t *)arg)->datapool_address));
2459 /* get the number of bytes */
2460 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2464 /* calculate the start of the data pool */
2465 data_pool_area_addr = sep_dev->shared_area_addr +
2466 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2468 /* check that the range of the virtual kernel address is correct */
2469 if ((virt_address < data_pool_area_addr) ||
2470 (virt_address > (data_pool_area_addr +
2471 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2476 /* copy the application data */
2477 error = copy_to_user((void *)app_out_address, (void *)virt_address,
2482 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2483 "SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
2490 this function handles tha request for creation of the DMA table
2491 for the synchronic symmetric operations (AES,DES)
2493 static int sep_create_sync_dma_tables_handler(unsigned long arg)
2498 /* command arguments */
2499 struct sep_driver_build_sync_table_t command_args;
2501 /*------------------------
2503 --------------------------*/
2505 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2506 "SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
2508 error = copy_from_user(&command_args,
2510 sizeof(struct sep_driver_build_sync_table_t));
2514 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2515 "app_in_address is %08lx\n",
2516 command_args.app_in_address);
2517 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2518 "app_out_address is %08lx\n",
2519 command_args.app_out_address);
2520 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2521 "data_size is %lu\n",
2522 command_args.data_in_size);
2523 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2524 "block_size is %lu\n",
2525 command_args.block_size);
2528 /* check if we need to build only input table or input/output */
2529 if (command_args.app_out_address)
2530 /* prepare input and output tables */
2531 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
2532 command_args.app_out_address,
2533 command_args.data_in_size,
2534 command_args.block_size,
2535 &command_args.in_table_address,
2536 &command_args.out_table_address,
2537 &command_args.in_table_num_entries,
2538 &command_args.out_table_num_entries,
2539 &command_args.table_data_size,
2540 command_args.isKernelVirtualAddress);
2542 /* prepare input tables */
2543 error = sep_prepare_input_dma_table(command_args.app_in_address,
2544 command_args.data_in_size,
2545 command_args.block_size,
2546 &command_args.in_table_address,
2547 &command_args.in_table_num_entries,
2548 &command_args.table_data_size,
2549 command_args.isKernelVirtualAddress);
2555 error = copy_to_user((void *)arg,
2556 (void *)&command_args,
2557 sizeof(struct sep_driver_build_sync_table_t));
2561 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2562 "SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
2568 this function handles the request for freeing dma table for synhronic actions
2570 int sep_free_dma_table_data_handler()
2572 /*-------------------------
2574 -----------------------------*/
2576 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2577 "SEP Driver:--------> sep_free_dma_table_data_handler start\n");
2579 /* free input pages array */
2580 sep_free_dma_pages(sep_dev->in_page_array,
2581 sep_dev->in_num_pages,
2584 /* free output pages array if needed */
2585 if (sep_dev->out_page_array)
2586 sep_free_dma_pages(sep_dev->out_page_array,
2587 sep_dev->out_num_pages,
2590 /* reset all the values */
2591 sep_dev->in_page_array = 0;
2592 sep_dev->out_page_array = 0;
2593 sep_dev->in_num_pages = 0;
2594 sep_dev->out_num_pages = 0;
2597 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2598 "SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
2604 this function handles the request to create the DMA tables for flow
2606 static int sep_create_flow_dma_tables_handler(unsigned long arg)
2611 /* command arguments */
2612 struct sep_driver_build_flow_table_t command_args;
2614 /* first table - output */
2615 struct sep_lli_entry_t first_table_data;
2617 /* dma table data */
2618 struct sep_lli_entry_t last_table_data;
2620 /* pointer to the info entry of the previuos DMA table */
2621 struct sep_lli_entry_t *prev_info_entry_ptr;
2623 /* pointer to the flow data strucutre */
2624 struct sep_flow_context_t *flow_context_ptr;
2626 /*------------------------
2628 --------------------------*/
2630 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2631 "SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
2633 /* init variables */
2634 prev_info_entry_ptr = 0;
2635 first_table_data.physical_address = 0xffffffff;
2637 /* find the free structure for flow data */
2638 error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
2642 error = copy_from_user(&command_args,
2644 sizeof(struct sep_driver_build_flow_table_t));
2648 /* create flow tables */
2649 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2650 command_args.virt_buff_data_addr,
2654 command_args.isKernelVirtualAddress);
2656 goto end_function_with_error;
2658 /* check if flow is static */
2659 if (!command_args.flow_type)
2660 /* point the info entry of the last to the info entry of the first */
2661 last_table_data = first_table_data;
2663 /* set output params */
2664 command_args.first_table_addr = first_table_data.physical_address;
2665 command_args.first_table_num_entries =
2666 ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
2667 SEP_NUM_ENTRIES_MASK);
2668 command_args.first_table_data_size =
2669 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2671 /* send the parameters to user application */
2672 error = copy_to_user((void *)arg,
2674 sizeof(struct sep_driver_build_flow_table_t));
2676 goto end_function_with_error;
2678 /* all the flow created - update the flow entry with temp id */
2679 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
2681 /* set the processing tables data in the context */
2682 if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
2683 flow_context_ptr->input_tables_in_process = first_table_data;
2685 flow_context_ptr->output_tables_in_process = first_table_data;
2689 end_function_with_error:
2691 /* free the allocated tables */
2692 sep_deallocated_flow_tables(&first_table_data);
2696 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2697 "SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
2704 this functio n handles add tables to flow
2706 static int sep_add_flow_tables_handler(unsigned long arg)
2711 /* number of entries */
2712 unsigned long num_entries;
2714 /* command arguments */
2715 struct sep_driver_add_flow_table_t command_args;
2717 /* pointer to the flow data strucutre */
2718 struct sep_flow_context_t *flow_context_ptr;
2720 /* first dma table data */
2721 struct sep_lli_entry_t first_table_data;
2723 /* last dma table data */
2724 struct sep_lli_entry_t last_table_data;
2726 /* pointer to the info entry of the current DMA table */
2727 struct sep_lli_entry_t *info_entry_ptr;
2729 /*--------------------------
2731 ----------------------------*/
2733 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2734 "SEP Driver:--------> sep_add_flow_tables_handler start\n");
2736 /* get input parameters */
2737 error = copy_from_user(&command_args,
2739 sizeof(struct sep_driver_add_flow_table_t));
2743 /* find the flow structure for the flow id */
2744 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2748 /* prepare the flow dma tables */
2749 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2750 command_args.virt_buff_data_addr,
2754 command_args.isKernelVirtualAddress);
2756 goto end_function_with_error;
2758 /* now check if there is already an existing add table for this flow */
2759 if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
2760 /* this buffer was for input buffers */
2761 if (flow_context_ptr->input_tables_flag) {
2762 /* add table already exists - add the new tables to the end
2764 num_entries = (flow_context_ptr->last_input_table.block_size >>
2765 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2768 (struct sep_lli_entry_t *)
2769 (flow_context_ptr->last_input_table.physical_address +
2770 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2772 /* connect to list of tables */
2773 *info_entry_ptr = first_table_data;
2775 /* set the first table data */
2776 first_table_data = flow_context_ptr->first_input_table;
2778 /* set the input flag */
2779 flow_context_ptr->input_tables_flag = 1;
2781 /* set the first table data */
2782 flow_context_ptr->first_input_table = first_table_data;
2784 /* set the last table data */
2785 flow_context_ptr->last_input_table = last_table_data;
2786 } else /* this is output tables */ {
2787 /* this buffer was for input buffers */
2788 if (flow_context_ptr->output_tables_flag) {
2789 /* add table already exists - add the new tables to
2790 the end of the previous */
2791 num_entries = (flow_context_ptr->last_output_table.block_size >>
2792 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2795 (struct sep_lli_entry_t *)
2796 (flow_context_ptr->last_output_table.physical_address +
2797 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2799 /* connect to list of tables */
2800 *info_entry_ptr = first_table_data;
2802 /* set the first table data */
2803 first_table_data = flow_context_ptr->first_output_table;
2805 /* set the input flag */
2806 flow_context_ptr->output_tables_flag = 1;
2808 /* set the first table data */
2809 flow_context_ptr->first_output_table = first_table_data;
2811 /* set the last table data */
2812 flow_context_ptr->last_output_table = last_table_data;
2815 /* set output params */
2816 command_args.first_table_addr = first_table_data.physical_address;
2817 command_args.first_table_num_entries = ((first_table_data.block_size >>
2818 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
2819 command_args.first_table_data_size =
2820 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2822 /* send the parameters to user application */
2823 error = copy_to_user((void *)arg,
2825 sizeof(struct sep_driver_add_flow_table_t));
2827 goto end_function_with_error;
2829 end_function_with_error:
2831 /* free the allocated tables */
2832 sep_deallocated_flow_tables(&first_table_data);
2836 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2837 "SEP Driver:<-------- sep_add_flow_tables_handler end\n");
2843 this function add the flow add message to the specific flow
2845 static int sep_add_flow_tables_message_handler(unsigned long arg)
2851 struct sep_driver_add_message_t command_args;
2854 struct sep_flow_context_t *flow_context_ptr;
2856 /*----------------------------
2858 ------------------------------*/
2860 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2861 "SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
2863 error = copy_from_user(&command_args,
2865 sizeof(struct sep_driver_add_message_t));
2870 if (command_args.message_size_in_bytes >
2871 SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
2876 /* find the flow context */
2877 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2881 /* copy the message into context */
2882 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
2884 error = copy_from_user(flow_context_ptr->message,
2885 (void *)command_args.message_address,
2886 command_args.message_size_in_bytes);
2891 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2892 "SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
2899 this function returns the physical and virtual addresses of the static pool
2901 static int sep_get_static_pool_addr_handler(unsigned long arg)
2906 /* command arguments */
2907 struct sep_driver_static_pool_addr_t command_args;
2909 /*-----------------------------
2911 ------------------------------*/
2913 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2914 "SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2916 /*prepare the output parameters in the struct */
2917 command_args.physical_static_address = sep_dev->phys_shared_area_addr +
2918 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2919 command_args.virtual_static_address = sep_dev->shared_area_addr +
2920 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2922 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2923 "SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
2924 command_args.physical_static_address,
2925 command_args.virtual_static_address);
2927 /* send the parameters to user application */
2928 error = copy_to_user((void *)arg,
2930 sizeof(struct sep_driver_static_pool_addr_t));
2936 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2937 "SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2943 this address gets the offset of the physical address from the start
2946 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2951 /* command arguments */
2952 struct sep_driver_get_mapped_offset_t command_args;
2954 /*-----------------------------
2956 ------------------------------*/
2958 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2959 "SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2961 error = copy_from_user(&command_args,
2963 sizeof(struct sep_driver_get_mapped_offset_t));
2967 if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2972 /*prepare the output parameters in the struct */
2973 command_args.offset = command_args.physical_address -
2974 sep_dev->phys_shared_area_addr;
2976 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2977 "SEP Driver:physical_address is %08lx, offset is %lu\n",
2978 command_args.physical_address,
2979 command_args.offset);
2981 /* send the parameters to user application */
2982 error = copy_to_user((void *)arg,
2984 sizeof(struct sep_driver_get_mapped_offset_t));
2990 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2991 "SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
3000 static int sep_start_handler(void)
3003 unsigned long reg_val;
3006 unsigned long error;
3008 /*-----------------------------
3010 ------------------------------*/
3012 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3013 "SEP Driver:--------> sep_start_handler start\n");
3017 /* wait in polling for message from SEP */
3019 SEP_READ_REGISTER(sep_dev->reg_base_address +
3020 HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
3023 /* check the value */
3024 if (reg_val == 0x1) {
3025 /* fatal error - read erro status from GPRO */
3026 SEP_READ_REGISTER(sep_dev->reg_base_address +
3027 HW_HOST_SEP_HOST_GPR0_REG_ADDR, error);
3033 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3034 "SEP Driver:<-------- sep_start_handler end\n");
3040 this function handles the request for SEP initialization
3042 static int sep_init_handler(unsigned long arg)
3044 /* word from message */
3045 unsigned long message_word;
3048 unsigned long *message_ptr;
3050 /* command arguments */
3051 struct sep_driver_init_t command_args;
3054 unsigned long counter;
3057 unsigned long error;
3060 unsigned long reg_val;
3062 /*-------------------
3064 ---------------------*/
3066 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3067 "SEP Driver:--------> sep_init_handler start\n");
3071 error = copy_from_user(&command_args, (void *)arg,
3072 sizeof(struct sep_driver_init_t));
3074 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3075 "SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
3080 /* PATCH - configure the DMA to single -burst instead of multi-burst */
3081 /*sep_configure_dma_burst();*/
3083 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3084 "SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
3086 message_ptr = (unsigned long *)command_args.message_addr;
3088 /* set the base address of the SRAM */
3089 SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3090 HW_SRAM_ADDR_REG_ADDR,
3091 HW_CC_SRAM_BASE_ADDRESS);
3094 counter < command_args.message_size_in_words;
3095 counter++, message_ptr++) {
3096 get_user(message_word, message_ptr);
3098 /* write data to SRAM */
3099 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_SRAM_DATA_REG_ADDR,
3102 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3103 "SEP Driver:message_word is %lu\n",
3106 /* wait for write complete */
3107 SEP_WAIT_SRAM_WRITE_COMPLETE();
3110 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3111 "SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
3114 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_HOST_SEP_GPR0_REG_ADDR,
3118 SEP_READ_REGISTER(sep_dev->reg_base_address +
3119 HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
3120 } while (!(reg_val & 0xFFFFFFFD));
3122 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3123 "SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
3125 /* check the value */
3126 if (reg_val == 0x1) {
3127 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
3128 "SEP Driver:init failed\n");
3130 SEP_READ_REGISTER(sep_dev->reg_base_address + 0x8060, error);
3131 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3132 "SEP Driver:sw monitor is %lu\n",
3135 /* fatal error - read erro status from GPRO */
3136 SEP_READ_REGISTER(sep_dev->reg_base_address +
3137 HW_HOST_SEP_HOST_GPR0_REG_ADDR,
3139 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3140 "SEP Driver:error is %lu\n", error);
3146 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3147 "SEP Driver:<-------- sep_init_handler end\n");
3154 this function handles the request cache and resident reallocation
3156 static int sep_realloc_cache_resident_handler(unsigned long arg)
3161 /* physical cache addr */
3162 unsigned long phys_cache_address;
3164 /* physical resident addr */
3165 unsigned long phys_resident_address;
3167 /* command arguments */
3168 struct sep_driver_realloc_cache_resident_t command_args;
3170 /*------------------
3172 ---------------------*/
3175 error = copy_from_user(&command_args,
3177 sizeof(struct sep_driver_realloc_cache_resident_t));
3181 /* copy cache and resident to the their intended locations */
3182 error = sep_copy_cache_resident_to_area(command_args.cache_addr,
3183 command_args.cache_size_in_bytes,
3184 command_args.resident_addr,
3185 command_args.resident_size_in_bytes,
3186 &phys_cache_address,
3187 &phys_resident_address);
3191 /* lock the area (if needed) */
3192 sep_lock_cache_resident_area();
3194 command_args.new_base_addr = sep_dev->phys_shared_area_addr;
3196 /* find the new base address according to the lowest address between
3197 cache, resident and shared area */
3198 if (phys_resident_address < command_args.new_base_addr)
3199 command_args.new_base_addr = phys_resident_address;
3200 if (phys_cache_address < command_args.new_base_addr)
3201 command_args.new_base_addr = phys_cache_address;
3203 /* set the return parameters */
3204 command_args.new_cache_addr = phys_cache_address;
3205 command_args.new_resident_addr = phys_resident_address;
3208 /* set the new shared area */
3209 command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
3211 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3212 "SEP Driver:command_args.new_shared_area_addr is %08lx\n",
3213 command_args.new_shared_area_addr);
3214 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3215 "SEP Driver:command_args.new_base_addr is %08lx\n",
3216 command_args.new_base_addr);
3217 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3218 "SEP Driver:command_args.new_resident_addr is %08lx\n",
3219 command_args.new_resident_addr);
3220 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3221 "SEP Driver:command_args.new_cache_addr is %08lx\n",
3222 command_args.new_cache_addr);
3224 /* return to user */
3225 error = copy_to_user((void *)arg,
3226 (void *)&command_args,
3227 sizeof(struct sep_driver_realloc_cache_resident_t));
3235 this function handles the request for get time
3237 static int sep_get_time_handler(unsigned long arg)
3242 /* command arguments */
3243 struct sep_driver_get_time_t command_args;
3245 /*------------------------
3247 --------------------------*/
3249 error = sep_set_time(&command_args.time_physical_address,
3250 &command_args.time_value);
3252 /* return to user */
3253 error = copy_to_user((void *)arg,
3254 (void *)&command_args,
3255 sizeof(struct sep_driver_get_time_t));
3262 This api handles the setting of API mode to blocking or non-blocking
3264 static int sep_set_api_mode_handler(unsigned long arg)
3270 unsigned long mode_flag;
3272 /*----------------------------
3274 -----------------------------*/
3276 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3277 "SEP Driver:--------> sep_set_api_mode_handler start\n");
3280 mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
3284 /* set the global flag */
3285 sep_dev->block_mode_flag = mode_flag;
3290 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3291 "SEP Driver:<-------- sep_set_api_mode_handler end\n");
3297 This API handles the end transaction request
3299 static int sep_end_transaction_handler(unsigned long arg)
3301 /*----------------------------
3303 -----------------------------*/
3305 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3306 "SEP Driver:--------> sep_end_transaction_handler start\n");
3308 #if 0/*!SEP_DRIVER_POLLING_MODE*/
3310 SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
3312 /* release IRQ line */
3313 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
3315 /* lock the sep mutex */
3316 mutex_unlock(&sep_mutex);
3319 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3320 "SEP Driver:<-------- sep_end_transaction_handler end\n");
3325 /* handler for flow done interrupt */
3326 static void sep_flow_done_handler(struct work_struct *work)
3328 /* flow context_ptr */
3329 struct sep_flow_context_t *flow_data_ptr;
3330 /*-------------------------
3332 ---------------------------*/
3334 /* obtain the mutex */
3335 mutex_lock(&sep_mutex);
3337 /* get the pointer to context */
3338 flow_data_ptr = (struct sep_flow_context_t *)work;
3340 /* free all the current input tables in sep */
3341 sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
3343 /* free all the current tables output tables in SEP (if needed) */
3344 if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
3345 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
3347 /* check if we have additional tables to be sent to SEP only input
3348 flag may be checked */
3349 if (flow_data_ptr->input_tables_flag) {
3350 /* copy the message to the shared RAM and signal SEP */
3351 memcpy((void *)flow_data_ptr->message,
3352 (void *)sep_dev->shared_area_addr,
3353 flow_data_ptr->message_size_in_bytes);
3355 SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3356 HW_HOST_HOST_SEP_GPR2_REG_ADDR,
3359 mutex_unlock(&sep_mutex);
3364 This function creates a list of tables for flow and returns the data for
3365 the first and last tables of the list
3367 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
3368 unsigned long first_buff_addr,
3369 struct sep_flow_context_t *flow_data_ptr,
3370 struct sep_lli_entry_t *first_table_data_ptr,
3371 struct sep_lli_entry_t *last_table_data_ptr,
3372 bool isKernelVirtualAddress)
3377 /* virtaul address of one buffer */
3378 unsigned long virt_buff_addr;
3380 /* virtual size of one buffer */
3381 unsigned long virt_buff_size;
3383 /* table data for each created table */
3384 struct sep_lli_entry_t table_data;
3387 struct sep_lli_entry_t *info_entry_ptr;
3389 /* prevouis info entry */
3390 struct sep_lli_entry_t *prev_info_entry_ptr;
3395 /*-------------------------------
3397 ----------------------------------*/
3401 prev_info_entry_ptr = 0;
3403 /* init the first table to default */
3404 table_data.physical_address = 0xffffffff;
3405 first_table_data_ptr->physical_address = 0xffffffff;
3406 table_data.block_size = 0;
3408 for (i = 0; i < num_virtual_buffers; i++) {
3409 /* get the virtual buffer address */
3410 error = get_user(virt_buff_addr, &first_buff_addr);
3414 /* get the virtual buffer size */
3416 error = get_user(virt_buff_size, &first_buff_addr);
3420 /* advance the address to point to the next pair of address|size */
3423 /* now prepare the one flow LLI table from the data */
3424 error = sep_prepare_one_flow_dma_table(virt_buff_addr,
3429 isKernelVirtualAddress);
3434 /* if this is the first table - save it to return to the user
3436 *first_table_data_ptr = table_data;
3438 /* set the pointer to info entry */
3439 prev_info_entry_ptr = info_entry_ptr;
3441 /* not first table - the previous table info entry should
3443 prev_info_entry_ptr->block_size =
3444 (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
3445 (table_data.block_size);
3447 /* set the pointer to info entry */
3448 prev_info_entry_ptr = info_entry_ptr;
3452 /* set the last table data */
3453 *last_table_data_ptr = table_data;
3462 This function creates one DMA table for flow and returns its data,
3463 and pointer to its info entry
3465 static int sep_prepare_one_flow_dma_table(
3466 unsigned long virt_buff_addr,
3467 unsigned long virt_buff_size,
3468 struct sep_lli_entry_t *table_data,
3469 struct sep_lli_entry_t **info_entry_ptr,
3470 struct sep_flow_context_t *flow_data_ptr,
3471 bool isKernelVirtualAddress)
3476 /* the range in pages */
3477 unsigned long lli_array_size;
3479 /* array of pointers ot page */
3480 struct sep_lli_entry_t *lli_array;
3482 /* pointer to the entry in the dma table */
3483 struct sep_lli_entry_t *flow_dma_table_entry_ptr;
3485 /* address of the dma table */
3486 unsigned long *start_dma_table_ptr;
3488 /* total table data counter */
3489 unsigned long dma_table_data_count;
3491 /* pointer that will keep the pointer t the pages of the virtual buffer */
3492 struct page **page_array_ptr;
3495 unsigned long entry_count;
3497 /*-------------------------------
3499 ----------------------------------*/
3501 /* find the space for the new table */
3502 error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
3506 /* check if the pages are in Kernel Virtual Address layout */
3507 if (isKernelVirtualAddress == true)
3508 /* lock kernel buffer in the memory */
3509 error = sep_lock_kernel_pages(virt_buff_addr,
3515 /* lock user buffer in the memory */
3516 error = sep_lock_user_pages(virt_buff_addr,
3525 /* set the pointer to page array at the beginning of table - this table is
3526 now considered taken */
3527 *start_dma_table_ptr = lli_array_size;
3529 /* point to the place of the pages pointers of the table */
3530 start_dma_table_ptr++;
3532 /* set the pages pointer */
3533 *start_dma_table_ptr = (unsigned long)page_array_ptr;
3535 /* set the pointer to the first entry */
3536 flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
3538 /* now create the entries for table */
3539 for (dma_table_data_count = entry_count = 0;
3540 entry_count < lli_array_size;
3542 flow_dma_table_entry_ptr->physical_address =
3543 lli_array[entry_count].physical_address;
3545 flow_dma_table_entry_ptr->block_size =
3546 lli_array[entry_count].block_size;
3548 /* set the total data of a table */
3549 dma_table_data_count += lli_array[entry_count].block_size;
3551 flow_dma_table_entry_ptr++;
3554 /* set the physical address */
3555 table_data->physical_address = virt_to_phys(start_dma_table_ptr);
3557 /* set the num_entries and total data size */
3558 table_data->block_size = ((lli_array_size + 1) <<
3559 SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
3560 (dma_table_data_count);
3562 /* set the info entry */
3563 flow_dma_table_entry_ptr->physical_address = 0xffffffff;
3564 flow_dma_table_entry_ptr->block_size = 0;
3566 /* set the pointer to info entry */
3567 *info_entry_ptr = flow_dma_table_entry_ptr;
3569 /* the array of the lli entries */
3579 This function returns pointer to the flow data structure
3580 that conatins the given id
3582 static int sep_find_flow_context(
3583 unsigned long flow_id,
3584 struct sep_flow_context_t **flow_data_ptr)
3587 unsigned long count;
3592 /*-----------------------
3594 ---------------------------*/
3599 always search for flow with id default first - in case we
3600 already started working on the flow there can be no situation
3601 when 2 flows are with default flag
3603 for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
3604 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
3605 *flow_data_ptr = &sep_dev->flows_data_array[count];
3610 if (count == SEP_DRIVER_NUM_FLOWS)
3618 this function find a space for the new flow dma table
3620 static int sep_find_free_flow_dma_table_space(
3621 unsigned long **table_address_ptr)
3626 /* pointer to the id field of the flow dma table */
3627 unsigned long *start_table_ptr;
3629 /* start address of the flow dma area */
3630 unsigned long flow_dma_area_start_addr;
3632 /* end address of the flow dma area */
3633 unsigned long flow_dma_area_end_addr;
3635 /* maximum table size in words */
3636 unsigned long table_size_in_words;
3638 /*---------------------
3640 -----------------------*/
3644 /* find the start address of the flow DMA table area */
3645 flow_dma_area_start_addr = sep_dev->shared_area_addr +
3646 SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
3648 /* set end address of the flow table area */
3649 flow_dma_area_end_addr = flow_dma_area_start_addr +
3650 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
3652 /* set table size in words */
3653 table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
3654 (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
3656 /* set the pointer to the start address of DMA area */
3657 start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
3659 /* find the space for the next table */
3660 while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
3661 ((unsigned long)start_table_ptr <
3662 flow_dma_area_end_addr))
3663 start_table_ptr += table_size_in_words;
3665 /* check if we reached the end of floa tables area */
3666 if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
3669 *table_address_ptr = start_table_ptr;
3675 this function goes over all the flow tables connected to the given
3676 table and deallocate them
3678 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
3681 unsigned long *table_ptr;
3683 /* end address of the flow dma area */
3684 unsigned long num_entries;
3686 unsigned long num_pages;
3689 struct page **pages_ptr;
3691 /* maximum table size in words */
3692 struct sep_lli_entry_t *info_entry_ptr;
3694 /*-------------------------------
3696 ---------------------------------*/
3698 /* set the pointer to the first table */
3699 table_ptr = (unsigned long *)first_table_ptr->physical_address;
3701 /* set the num of entries */
3702 num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
3703 & SEP_NUM_ENTRIES_MASK;
3705 /* go over all the connected tables */
3706 while (*table_ptr != 0xffffffff) {
3707 /* get number of pages */
3708 num_pages = *(table_ptr - 2);
3710 /* get the pointer to the pages */
3711 pages_ptr = (struct page **)(*(table_ptr - 1));
3713 /* free the pages */
3714 sep_free_dma_pages(pages_ptr, num_pages, 1);
3716 /* goto to the info entry */
3717 info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
3720 table_ptr = (unsigned long *)info_entry_ptr->physical_address;
3721 num_entries = (info_entry_ptr->block_size >>
3722 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
3729 This function handler the set flow id command
3731 static int sep_set_flow_id_handler(unsigned long arg)
3737 unsigned long flow_id;
3739 /* pointer to flow data structre */
3740 struct sep_flow_context_t *flow_data_ptr;
3742 /*----------------------
3744 -----------------------*/
3746 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3747 "------------>SEP Driver: sep_set_flow_id_handler start\n");
3749 error = get_user(flow_id,
3750 &(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
3754 /* find the flow data structure that was just used for creating new flow
3755 - its id should be default */
3756 error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
3761 flow_data_ptr->flow_id = flow_id;
3765 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3766 "SEP Driver:<-------- sep_set_flow_id_handler end\n");
3774 calculates time and sets it at the predefined address
3776 static int sep_set_time(unsigned long *address_ptr,
3777 unsigned long *time_in_sec_ptr)
3780 struct timeval time;
3782 /* address of time in the kernel */
3783 unsigned long time_addr;
3786 /*------------------------
3788 --------------------------*/
3790 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3791 "SEP Driver:--------> sep_set_time start\n");
3794 do_gettimeofday(&time);
3796 /* set value in the SYSTEM MEMORY offset */
3797 time_addr = sep_dev->message_shared_area_addr +
3798 SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
3800 *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
3801 *(unsigned long *)(time_addr + 4) = time.tv_sec;
3803 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3804 "SEP Driver:time.tv_sec is %lu\n",
3806 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3807 "SEP Driver:time_addr is %lu\n",
3809 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3810 "SEP Driver:g_message_shared_area_addr is %lu\n",
3811 sep_dev->message_shared_area_addr);
3813 /* set the output parameters if needed */
3815 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
3817 if (time_in_sec_ptr)
3818 *time_in_sec_ptr = time.tv_sec;
3820 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3821 "SEP Driver:<-------- sep_set_time end\n");
3827 PATCH for configuring the DMA to single burst instead of multi-burst
3829 static void sep_configure_dma_burst(void)
3832 #define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL
3834 unsigned long regVal;
3836 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3837 "SEP Driver:<-------- sep_configure_dma_burst start \n");
3839 /* request access to registers from SEP */
3840 SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3841 HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2UL);
3843 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3844 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n");
3846 SEP_READ_REGISTER(sep_dev->reg_base_address +
3847 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3849 SEP_READ_REGISTER(sep_dev->reg_base_address +
3850 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3852 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3853 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n");
3855 /* set the DMA burst register to single burst*/
3856 SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3857 HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
3859 /* release the sep busy */
3860 SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3861 HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
3862 SEP_READ_REGISTER(sep_dev->reg_base_address +
3863 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3864 while (regVal != 0x0)
3865 SEP_READ_REGISTER(sep_dev->reg_base_address +
3866 HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3868 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3869 "SEP Driver:<-------- sep_configure_dma_burst done \n");
3873 module_init(sep_init);
3874 module_exit(sep_exit);
3876 MODULE_LICENSE("GPL");