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 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
379 sep_dev->sep_to_host_reply_counter++;
381 /* poll, until reply from sep */
382 wait_event(g_sep_event,
383 (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
388 /*----------------------------------------------------------------------
389 open function of the character driver - must only lock the mutex
390 must also release the memory data pool allocations
391 ------------------------------------------------------------------------*/
392 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
399 ---------------------*/
401 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> open start\n");
405 /* check the blocking mode */
406 if (sep_dev->block_mode_flag)
408 mutex_lock(&sep_mutex);
410 error = mutex_trylock(&sep_mutex);
412 /* check the error */
414 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
415 "SEP Driver: down_interruptible failed\n");
420 /* release data pool allocations */
421 sep_dev->data_pool_bytes_allocated = 0;
425 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- open end\n");
433 /*------------------------------------------------------------
435 -------------------------------------------------------------*/
436 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
440 ---------------------*/
442 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
443 "----------->SEP Driver: sep_release start\n");
445 #if 0/*!SEP_DRIVER_POLLING_MODE*/
447 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
449 /* release IRQ line */
450 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
454 /* unlock the sep mutex */
455 mutex_unlock(&sep_mutex);
457 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
458 "SEP Driver:<-------- sep_release end\n");
466 /*---------------------------------------------------------------
467 map function - this functions maps the message shared area
468 -----------------------------------------------------------------*/
469 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
472 unsigned long phys_addr;
474 /*-----------------------
476 -------------------------*/
478 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "-------->SEP Driver: mmap start\n");
480 /* check that the size of the mapped range is as the size of the message
482 if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
483 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
484 "SEP Driver mmap requested size is more than allowed\n");
485 printk(KERN_WARNING "SEP Driver mmap requested size is more \
487 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
489 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
494 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
495 "SEP Driver:g_message_shared_area_addr is %08lx\n",
496 sep_dev->message_shared_area_addr);
498 /* get physical address */
499 phys_addr = sep_dev->phys_shared_area_addr;
501 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: phys_addr is %08lx\n",
504 if (remap_pfn_range(vma,
506 phys_addr >> PAGE_SHIFT,
507 vma->vm_end - vma->vm_start,
508 vma->vm_page_prot)) {
509 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
510 "SEP Driver remap_page_range failed\n");
511 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
515 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- mmap end\n");
521 /*-----------------------------------------------
523 *----------------------------------------------*/
524 static unsigned int sep_poll(struct file *filp, poll_table *wait)
528 unsigned int mask = 0;
531 unsigned long retVal = 0;
533 /*----------------------------------------------
535 -------------------------------------------------*/
537 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "---------->SEP Driver poll: start\n");
540 #if SEP_DRIVER_POLLING_MODE
542 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
543 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
545 for (count = 0; count < 10 * 4; count += 4)
546 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
547 "Poll Debug Word %lu of the message is %lu\n",
549 *((unsigned long *)(sep_dev->shared_area_addr +
550 SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
553 sep_dev->sep_to_host_reply_counter++;
555 /* add the event to the polling wait table */
556 poll_wait(filp, &g_sep_event, wait);
560 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
561 "sep_dev->host_to_sep_send_counter is %lu\n",
562 sep_dev->host_to_sep_send_counter);
563 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
564 "sep_dev->sep_to_host_reply_counter is %lu\n",
565 sep_dev->sep_to_host_reply_counter);
567 /* check if the data is ready */
568 if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
569 for (count = 0; count < 12 * 4; count += 4)
570 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
571 "Sep Mesg Word %lu of the message is %lu\n",
572 count, *((unsigned long *)(sep_dev->shared_area_addr + count)));
574 for (count = 0; count < 10 * 4; count += 4)
575 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
576 "Debug Data Word %lu of the message is %lu\n",
578 *((unsigned long *)(sep_dev->shared_area_addr + 0x1800 + count)));
580 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
581 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "retVal is %lu\n", retVal);
582 /* check if the this is sep reply or request */
584 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
585 "SEP Driver: sep request in\n");
587 mask |= POLLOUT | POLLWRNORM;
589 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: sep reply in\n");
590 mask |= POLLIN | POLLRDNORM;
594 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- poll exit\n");
599 static int sep_ioctl(struct inode *inode,
608 /*------------------------
610 ------------------------*/
613 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
614 "------------>SEP Driver: ioctl start\n");
616 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: cmd is %x\n", cmd);
618 /* check that the command is for sep device */
619 if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
623 case SEP_IOCSENDSEPCOMMAND:
625 /* send command to SEP */
626 sep_send_command_handler();
628 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
629 "SEP Driver: after sep_send_command_handler\n");
633 case SEP_IOCSENDSEPRPLYCOMMAND:
635 /* send reply command to SEP */
636 sep_send_reply_command_handler();
640 case SEP_IOCALLOCDATAPOLL:
642 /* allocate data pool */
643 error = sep_allocate_data_pool_memory_handler(arg);
647 case SEP_IOCWRITEDATAPOLL:
649 /* write data into memory pool */
650 error = sep_write_into_data_pool_handler(arg);
654 case SEP_IOCREADDATAPOLL:
656 /* read data from data pool into application memory */
657 error = sep_read_from_data_pool_handler(arg);
661 case SEP_IOCCREATESYMDMATABLE:
663 /* create dma table for synhronic operation */
664 error = sep_create_sync_dma_tables_handler(arg);
668 case SEP_IOCCREATEFLOWDMATABLE:
670 /* create flow dma tables */
671 error = sep_create_flow_dma_tables_handler(arg);
675 case SEP_IOCFREEDMATABLEDATA:
678 error = sep_free_dma_table_data_handler();
682 case SEP_IOCSETFLOWID:
685 error = sep_set_flow_id_handler(arg);
689 case SEP_IOCADDFLOWTABLE:
691 /* add tables to the dynamic flow */
692 error = sep_add_flow_tables_handler(arg);
696 case SEP_IOCADDFLOWMESSAGE:
698 /* add message of add tables to flow */
699 error = sep_add_flow_tables_message_handler(arg);
703 case SEP_IOCSEPSTART:
705 /* start command to sep */
706 error = sep_start_handler();
711 /* init command to sep */
712 error = sep_init_handler(arg);
715 case SEP_IOCSETAPIMODE:
717 /* set non- blocking mode */
718 error = sep_set_api_mode_handler(arg);
722 case SEP_IOCGETSTATICPOOLADDR:
724 /* get the physical and virtual addresses of the static pool */
725 error = sep_get_static_pool_addr_handler(arg);
729 case SEP_IOCENDTRANSACTION:
731 error = sep_end_transaction_handler(arg);
735 case SEP_IOCREALLOCCACHERES:
737 error = sep_realloc_cache_resident_handler(arg);
741 case SEP_IOCGETMAPPEDADDROFFSET:
743 error = sep_get_physical_mapped_offset_handler(arg);
748 error = sep_get_time_handler(arg);
757 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
758 "SEP Driver:<-------- ioctl end\n");
765 this function registers the driver to the file system
767 static int sep_register_driver_to_fs(void)
772 /*---------------------
774 -----------------------*/
776 ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
778 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
779 "sep_driver:major number allocation failed, retval is %d\n", ret_val);
783 /* set the files operations structure */
784 g_sep_fops.owner = THIS_MODULE;
785 g_sep_fops.ioctl = sep_ioctl;
786 g_sep_fops.poll = sep_poll;
787 g_sep_fops.open = sep_open;
788 g_sep_fops.release = sep_release;
789 g_sep_fops.mmap = sep_mmap;
792 cdev_init(&g_sep_cdev, &g_sep_fops);
793 g_sep_cdev.owner = THIS_MODULE;
795 /* register the driver with the kernel */
796 ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
799 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
800 "sep_driver:cdev_add failed, retval is %d\n",
802 goto end_function_unregister_devnum;
807 end_function_unregister_devnum:
809 /* unregister dev numbers */
810 unregister_chrdev_region(g_sep_device_number, 1);
818 this function unregisters driver from fs
820 static void sep_unregister_driver_from_fs(void)
822 /*-------------------
824 ---------------------*/
826 cdev_del(&g_sep_cdev);
828 /* unregister dev numbers */
829 unregister_chrdev_region(g_sep_device_number, 1);
832 /*--------------------------------------------------------------
834 ----------------------------------------------------------------*/
835 static int __init sep_init(void)
843 /* size to of memory for allocation */
846 /*------------------------
848 ------------------------*/
850 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
851 "SEP Driver:-------->Init start\n");
852 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
853 "g_sep_shared_area_addr = %lx\n",
854 (unsigned long)&sep_dev->shared_area_addr);
858 /* transaction counter that coordinates the transactions between SEP
860 sep_dev->host_to_sep_send_counter = 0;
862 /* counter for the messages from sep */
863 sep_dev->sep_to_host_reply_counter = 0;
865 /* counter for the number of bytes allocated in the pool
866 for the current transaction */
867 sep_dev->data_pool_bytes_allocated = 0;
869 /* set the starting mode to blocking */
870 sep_dev->block_mode_flag = 1;
873 ret_val = sep_register_driver_to_device();
875 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
876 "sep_driver:sep_driver_to_device failed, ret_val is %d\n",
878 goto end_function_unregister_from_fs;
881 /* calculate the total size for allocation */
882 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
883 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
884 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
885 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
886 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
887 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
891 /* allocate the shared area */
892 if (sep_map_and_alloc_shared_area(size,
893 &sep_dev->shared_area_addr,
894 &sep_dev->phys_shared_area_addr)) {
896 /* allocation failed */
897 goto end_function_unmap_io_memory;
900 /* now set the memory regions */
901 sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
903 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
904 "SEP Driver: g_message_shared_area_addr is %08lx\n",
905 sep_dev->message_shared_area_addr);
907 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
909 /* send the new SHARED MESSAGE AREA to the SEP */
910 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR,
911 sep_dev->phys_shared_area_addr);
913 /* poll for SEP response */
914 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
915 while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
916 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
918 /* check the return value (register) */
919 if (retVal != sep_dev->phys_shared_area_addr) {
921 goto end_function_deallocate_message_area;
926 /* init the flow contextes */
927 for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
928 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
930 sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
931 if (sep_dev->flow_wq_ptr == 0) {
933 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
934 "sep_driver:flow queue creation failed\n");
935 goto end_function_deallocate_sep_shared_area;
938 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
939 "SEP Driver: create flow workqueue \n");
941 /* register driver to fs */
942 ret_val = sep_register_driver_to_fs();
944 goto end_function_deallocate_sep_shared_area;
946 /* load the rom code */
951 end_function_unregister_from_fs:
953 /* unregister from fs */
954 sep_unregister_driver_from_fs();
956 end_function_deallocate_sep_shared_area:
958 /* de-allocate shared area */
959 sep_unmap_and_free_shared_area(size,
960 sep_dev->shared_area_addr,
961 sep_dev->phys_shared_area_addr);
963 end_function_unmap_io_memory:
965 iounmap((void *)sep_dev->reg_base_address);
967 /* release io memory region */
968 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
972 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- Init end\n");
980 /*-------------------------------------------------------------
982 --------------------------------------------------------------*/
983 static void __exit sep_exit(void)
988 /*-----------------------------
990 --------------------------------*/
992 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> Exit start\n");
994 /* unregister from fs */
995 sep_unregister_driver_from_fs();
997 /* calculate the total size for de-allocation */
998 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
999 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
1000 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
1001 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
1002 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
1003 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
1006 /* free shared area */
1007 sep_unmap_and_free_shared_area(size,
1008 sep_dev->shared_area_addr,
1009 sep_dev->phys_shared_area_addr);
1011 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1012 "SEP Driver: free pages SEP SHARED AREA \n");
1014 iounmap((void *)sep_dev->reg_base_address);
1016 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: iounmap \n");
1018 /* release io memory region */
1019 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1021 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: release_mem_region \n");
1023 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- Exit end\n");
1028 interrupt handler function
1030 irqreturn_t sep_inthandler(int irq, void *dev_id)
1033 irqreturn_t int_error;
1036 unsigned long error;
1039 unsigned long reg_val;
1042 unsigned long flow_id;
1045 struct sep_flow_context_t *flow_context_ptr;
1047 /*-----------------------------
1049 -----------------------------*/
1051 int_error = IRQ_HANDLED;
1053 /* read the IRR register to check if this is SEP interrupt */
1054 reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
1055 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Interrupt - reg is %08lx\n",
1058 /* check if this is the flow interrupt */
1059 if (0/*reg_val & (0x1 << 11)*/) {
1060 /* read GPRO to find out the which flow is done */
1061 flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
1063 /* find the contex of the flow */
1064 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
1066 goto end_function_with_error;
1068 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
1070 /* queue the work */
1071 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
1074 /* check if this is reply interrupt from SEP */
1075 if (reg_val & (0x1 << 13)) {
1076 /* update the counter of reply messages */
1077 sep_dev->sep_to_host_reply_counter++;
1079 /* wake up the waiting process */
1080 wake_up(&g_sep_event);
1082 int_error = IRQ_NONE;
1087 end_function_with_error:
1089 /* clear the interrupt */
1090 sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
1099 This function prepares only input DMA table for synhronic symmetric
1102 int sep_prepare_input_dma_table(unsigned long app_virt_addr,
1103 unsigned long data_size,
1104 unsigned long block_size,
1105 unsigned long *lli_table_ptr,
1106 unsigned long *num_entries_ptr,
1107 unsigned long *table_data_size_ptr,
1108 bool isKernelVirtualAddress)
1111 /* pointer to the info entry of the table - the last entry */
1112 struct sep_lli_entry_t *info_entry_ptr;
1114 /* array of pointers ot page */
1115 struct sep_lli_entry_t *lli_array_ptr;
1117 /* points to the first entry to be processed in the lli_in_array */
1118 unsigned long current_entry;
1120 /* num entries in the virtual buffer */
1121 unsigned long sep_lli_entries;
1123 /* lli table pointer */
1124 struct sep_lli_entry_t *in_lli_table_ptr;
1126 /* the total data in one table */
1127 unsigned long table_data_size;
1129 /* number of entries in lli table */
1130 unsigned long num_entries_in_table;
1132 /* next table address */
1133 unsigned long lli_table_alloc_addr;
1136 unsigned long result;
1138 /*------------------------
1140 --------------------------*/
1142 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1143 "SEP Driver:--------> sep_prepare_input_dma_table start\n");
1145 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:data_size is %lu\n",
1147 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:block_size is %lu\n",
1150 /* initialize the pages pointers */
1151 sep_dev->in_page_array = 0;
1152 sep_dev->in_num_pages = 0;
1154 if (data_size == 0) {
1155 /* special case - created 2 entries table with zero data */
1156 in_lli_table_ptr = (struct sep_lli_entry_t *)(sep_dev->shared_area_addr +
1157 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1158 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr +
1159 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1160 in_lli_table_ptr->block_size = 0;
1163 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1164 in_lli_table_ptr->block_size = 0;
1166 *lli_table_ptr = sep_dev->phys_shared_area_addr +
1167 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1168 *num_entries_ptr = 2;
1169 *table_data_size_ptr = 0;
1174 /* check if the pages are in Kernel Virtual Address layout */
1175 if (isKernelVirtualAddress == true)
1176 /* lock the pages of the kernel buffer and translate them to pages */
1177 result = sep_lock_kernel_pages(app_virt_addr,
1179 &sep_dev->in_num_pages,
1181 &sep_dev->in_page_array);
1183 /* lock the pages of the user buffer and translate them to pages */
1184 result = sep_lock_user_pages(app_virt_addr,
1186 &sep_dev->in_num_pages,
1188 &sep_dev->in_page_array);
1193 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1194 "SEP Driver:output sep_dev->in_num_pages is %lu\n",
1195 sep_dev->in_num_pages);
1199 sep_lli_entries = sep_dev->in_num_pages;
1201 /* initiate to point after the message area */
1202 lli_table_alloc_addr = sep_dev->shared_area_addr +
1203 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1205 /* loop till all the entries in in array are not processed */
1206 while (current_entry < sep_lli_entries) {
1207 /* set the new input and output tables */
1208 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1210 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1211 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1213 /* calculate the maximum size of data for input table */
1214 table_data_size = sep_calculate_lli_table_max_size(
1215 &lli_array_ptr[current_entry],
1216 (sep_lli_entries - current_entry));
1218 /* now calculate the table size so that it will be module block size */
1219 table_data_size = (table_data_size / block_size) * block_size;
1221 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1222 "SEP Driver:output table_data_size is %lu\n",
1225 /* construct input lli table */
1226 sep_build_lli_table(&lli_array_ptr[current_entry],
1229 &num_entries_in_table,
1232 if (info_entry_ptr == 0) {
1233 /* set the output parameters to physical addresses */
1234 *lli_table_ptr = sep_shared_area_virt_to_phys(
1235 (unsigned long)in_lli_table_ptr);
1236 *num_entries_ptr = num_entries_in_table;
1237 *table_data_size_ptr = table_data_size;
1239 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1240 "SEP Driver:output lli_table_in_ptr is %08lx\n",
1243 /* update the info entry of the previous in table */
1244 info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
1245 (unsigned long)in_lli_table_ptr);
1246 info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
1250 /* save the pointer to the info entry of the current tables */
1251 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1254 /* print input tables */
1255 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1256 sep_shared_area_phys_to_virt(*lli_table_ptr),
1258 *table_data_size_ptr);
1260 /* the array of the pages */
1261 kfree(lli_array_ptr);
1265 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1266 "SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1273 This function builds input and output DMA tables for synhronic
1274 symmetric operations (AES, DES). It also checks that each table
1275 is of the modular block size
1277 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
1278 unsigned long app_virt_out_addr,
1279 unsigned long data_size,
1280 unsigned long block_size,
1281 unsigned long *lli_table_in_ptr,
1282 unsigned long *lli_table_out_ptr,
1283 unsigned long *in_num_entries_ptr,
1284 unsigned long *out_num_entries_ptr,
1285 unsigned long *table_data_size_ptr,
1286 bool isKernelVirtualAddress)
1289 /* array of pointers of page */
1290 struct sep_lli_entry_t *lli_in_array;
1292 /* array of pointers of page */
1293 struct sep_lli_entry_t *lli_out_array;
1299 /*------------------------
1301 --------------------------*/
1303 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1304 "SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1308 /* initialize the pages pointers */
1309 sep_dev->in_page_array = 0;
1310 sep_dev->out_page_array = 0;
1312 /* check if the pages are in Kernel Virtual Address layout */
1313 if (isKernelVirtualAddress == true) {
1314 /* lock the pages of the kernel buffer and translate them to pages */
1315 result = sep_lock_kernel_pages(app_virt_in_addr,
1317 &sep_dev->in_num_pages,
1319 &sep_dev->in_page_array);
1321 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1322 "SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1326 /* lock the pages of the user buffer and translate them to pages */
1327 result = sep_lock_user_pages(app_virt_in_addr,
1329 &sep_dev->in_num_pages,
1331 &sep_dev->in_page_array);
1333 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1334 "SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1339 if (isKernelVirtualAddress == true) {
1340 result = sep_lock_kernel_pages(app_virt_out_addr,
1342 &sep_dev->out_num_pages,
1344 &sep_dev->out_page_array);
1346 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1347 "SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1348 goto end_function_with_error1;
1351 result = sep_lock_user_pages(app_virt_out_addr,
1353 &sep_dev->out_num_pages,
1355 &sep_dev->out_page_array);
1357 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1358 "SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1359 goto end_function_with_error1;
1364 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1365 "sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1366 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1367 "sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1368 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1369 "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
1370 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1373 /* call the fucntion that creates table from the lli arrays */
1374 result = sep_construct_dma_tables_from_lli(lli_in_array,
1375 sep_dev->in_num_pages,
1377 sep_dev->out_num_pages,
1382 out_num_entries_ptr,
1383 table_data_size_ptr);
1385 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1386 "SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1387 goto end_function_with_error2;
1390 /* fall through - free the lli entry arrays */
1392 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "in_num_entries_ptr is %08lx\n",
1393 *in_num_entries_ptr);
1394 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "out_num_entries_ptr is %08lx\n",
1395 *out_num_entries_ptr);
1396 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "table_data_size_ptr is %08lx\n",
1397 *table_data_size_ptr);
1400 end_function_with_error2:
1402 kfree(lli_out_array);
1404 end_function_with_error1:
1406 kfree(lli_in_array);
1410 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1411 "SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n",
1420 This function creates the input and output dma tables for
1421 symmetric operations (AES/DES) according to the block size from LLI arays
1423 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
1424 unsigned long sep_in_lli_entries,
1425 struct sep_lli_entry_t *lli_out_array,
1426 unsigned long sep_out_lli_entries,
1427 unsigned long block_size,
1428 unsigned long *lli_table_in_ptr,
1429 unsigned long *lli_table_out_ptr,
1430 unsigned long *in_num_entries_ptr,
1431 unsigned long *out_num_entries_ptr,
1432 unsigned long *table_data_size_ptr)
1434 /* points to the area where next lli table can be allocated */
1435 unsigned long lli_table_alloc_addr;
1437 /* input lli table */
1438 struct sep_lli_entry_t *in_lli_table_ptr;
1440 /* output lli table */
1441 struct sep_lli_entry_t *out_lli_table_ptr;
1443 /* pointer to the info entry of the table - the last entry */
1444 struct sep_lli_entry_t *info_in_entry_ptr;
1446 /* pointer to the info entry of the table - the last entry */
1447 struct sep_lli_entry_t *info_out_entry_ptr;
1449 /* points to the first entry to be processed in the lli_in_array */
1450 unsigned long current_in_entry;
1452 /* points to the first entry to be processed in the lli_out_array */
1453 unsigned long current_out_entry;
1455 /* max size of the input table */
1456 unsigned long in_table_data_size;
1458 /* max size of the output table */
1459 unsigned long out_table_data_size;
1461 /* flag te signifies if this is the first tables build from the arrays */
1462 unsigned long first_table_flag;
1464 /* the data size that should be in table */
1465 unsigned long table_data_size;
1467 /* number of etnries in the input table */
1468 unsigned long num_entries_in_table;
1470 /* number of etnries in the output table */
1471 unsigned long num_entries_out_table;
1473 /*---------------------
1475 ------------------------*/
1477 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1478 "SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1480 /* initiate to pint after the message area */
1481 lli_table_alloc_addr = sep_dev->shared_area_addr +
1482 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1484 current_in_entry = 0;
1485 current_out_entry = 0;
1486 first_table_flag = 1;
1487 info_in_entry_ptr = 0;
1488 info_out_entry_ptr = 0;
1490 /* loop till all the entries in in array are not processed */
1491 while (current_in_entry < sep_in_lli_entries) {
1492 /* set the new input and output tables */
1493 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1495 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1496 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1498 /* set the first output tables */
1499 out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1501 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1502 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1504 /* calculate the maximum size of data for input table */
1505 in_table_data_size =
1506 sep_calculate_lli_table_max_size(
1507 &lli_in_array[current_in_entry],
1508 (sep_in_lli_entries - current_in_entry));
1510 /* calculate the maximum size of data for output table */
1511 out_table_data_size =
1512 sep_calculate_lli_table_max_size(
1513 &lli_out_array[current_out_entry],
1514 (sep_out_lli_entries - current_out_entry));
1516 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1517 "SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1518 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1519 "SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1521 /* check where the data is smallest */
1522 table_data_size = in_table_data_size;
1523 if (table_data_size > out_table_data_size)
1524 table_data_size = out_table_data_size;
1526 /* now calculate the table size so that it will be module block size */
1527 table_data_size = (table_data_size / block_size) * block_size;
1529 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1530 "SEP Driver:table_data_size is %lu\n",
1533 /* construct input lli table */
1534 sep_build_lli_table(&lli_in_array[current_in_entry],
1537 &num_entries_in_table,
1540 /* construct output lli table */
1541 sep_build_lli_table(&lli_out_array[current_out_entry],
1544 &num_entries_out_table,
1547 /* if info entry is null - this is the first table built */
1548 if (info_in_entry_ptr == 0) {
1549 /* set the output parameters to physical addresses */
1551 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1552 *in_num_entries_ptr = num_entries_in_table;
1553 *lli_table_out_ptr =
1554 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1555 *out_num_entries_ptr = num_entries_out_table;
1556 *table_data_size_ptr = table_data_size;
1558 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1559 "SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1560 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1561 "SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1563 /* update the info entry of the previous in table */
1564 info_in_entry_ptr->physical_address =
1565 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1566 info_in_entry_ptr->block_size =
1567 ((num_entries_in_table) << 24) | (table_data_size);
1569 /* update the info entry of the previous in table */
1570 info_out_entry_ptr->physical_address =
1571 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1572 info_out_entry_ptr->block_size =
1573 ((num_entries_out_table) << 24) | (table_data_size);
1576 /* save the pointer to the info entry of the current tables */
1577 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1578 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1580 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1581 "SEP Driver:output num_entries_out_table is %lu\n",
1582 (unsigned long)num_entries_out_table);
1583 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1584 "SEP Driver:output info_in_entry_ptr is %lu\n",
1585 (unsigned long)info_in_entry_ptr);
1586 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1587 "SEP Driver:output info_out_entry_ptr is %lu\n",
1588 (unsigned long)info_out_entry_ptr);
1591 /* print input tables */
1592 sep_debug_print_lli_tables(
1593 (struct sep_lli_entry_t *)
1594 sep_shared_area_phys_to_virt(*lli_table_in_ptr),
1595 *in_num_entries_ptr,
1596 *table_data_size_ptr);
1598 /* print output tables */
1599 sep_debug_print_lli_tables(
1600 (struct sep_lli_entry_t *)
1601 sep_shared_area_phys_to_virt(*lli_table_out_ptr),
1602 *out_num_entries_ptr,
1603 *table_data_size_ptr);
1605 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1606 "SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1612 this function calculates the size of data that can be inserted into the lli
1613 table from this array the condition is that either the table is full
1614 (all etnries are entered), or there are no more entries in the lli array
1616 unsigned long sep_calculate_lli_table_max_size(
1617 struct sep_lli_entry_t *lli_in_array_ptr,
1618 unsigned long num_array_entries)
1620 /* table data size */
1621 unsigned long table_data_size;
1624 unsigned long counter;
1626 /*---------------------
1628 ----------------------*/
1630 table_data_size = 0;
1632 /* calculate the data in the out lli table if till we fill the whole
1633 table or till the data has ended */
1635 (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
1636 (counter < num_array_entries); counter++)
1637 table_data_size += lli_in_array_ptr[counter].block_size;
1639 return table_data_size;
1643 this functions builds ont lli table from the lli_array according to
1644 the given size of data
1646 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
1647 struct sep_lli_entry_t *lli_table_ptr,
1648 unsigned long *num_processed_entries_ptr,
1649 unsigned long *num_table_entries_ptr,
1650 unsigned long table_data_size)
1652 /* current table data size */
1653 unsigned long curr_table_data_size;
1655 /* counter of lli array entry */
1656 unsigned long array_counter;
1658 /*-----------------------
1660 ---------------------------*/
1662 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1663 "SEP Driver:--------> sep_build_lli_table start\n");
1665 /* init currrent table data size and lli array entry counter */
1666 curr_table_data_size = 0;
1668 *num_table_entries_ptr = 1;
1670 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1671 "SEP Driver:table_data_size is %lu\n",
1674 /* fill the table till table size reaches the needed amount */
1675 while (curr_table_data_size < table_data_size) {
1676 /* update the number of entries in table */
1677 (*num_table_entries_ptr)++;
1679 lli_table_ptr->physical_address =
1680 lli_array_ptr[array_counter].physical_address;
1681 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1682 curr_table_data_size += lli_table_ptr->block_size;
1684 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1685 "SEP Driver:lli_table_ptr is %08lx\n",
1686 (unsigned long)lli_table_ptr);
1687 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1688 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1689 lli_table_ptr->physical_address);
1690 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1691 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1692 lli_table_ptr->block_size);
1694 /* check for overflow of the table data */
1695 if (curr_table_data_size > table_data_size) {
1696 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1697 "SEP Driver:curr_table_data_size > table_data_size\n");
1699 /* update the size of block in the table */
1700 lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1702 /* update the physical address in the lli array */
1703 lli_array_ptr[array_counter].physical_address +=
1704 lli_table_ptr->block_size;
1706 /* update the block size left in the lli array */
1707 lli_array_ptr[array_counter].block_size =
1708 (curr_table_data_size - table_data_size);
1710 /* advance to the next entry in the lli_array */
1713 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1714 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1715 lli_table_ptr->physical_address);
1716 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1717 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1718 lli_table_ptr->block_size);
1720 /* move to the next entry in table */
1724 /* set the info entry to default */
1725 lli_table_ptr->physical_address = 0xffffffff;
1726 lli_table_ptr->block_size = 0;
1728 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1729 "SEP Driver:lli_table_ptr is %08lx\n",
1730 (unsigned long)lli_table_ptr);
1731 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1732 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1733 lli_table_ptr->physical_address);
1734 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1735 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1736 lli_table_ptr->block_size);
1739 /* set the output parameter */
1740 *num_processed_entries_ptr += array_counter;
1742 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1743 "SEP Driver:*num_processed_entries_ptr is %lu\n",
1744 *num_processed_entries_ptr);
1747 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1748 "SEP Driver:<-------- sep_build_lli_table end\n");
1754 this function goes over the list of the print created tables and
1757 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
1758 unsigned long num_table_entries,
1759 unsigned long table_data_size)
1761 unsigned long table_count;
1763 unsigned long entries_count;
1764 /*-----------------------------
1766 -------------------------------*/
1768 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1769 "SEP Driver:--------> sep_debug_print_lli_tables start\n");
1772 while ((unsigned long)lli_table_ptr != 0xffffffff) {
1773 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1774 "SEP Driver: lli table %08lx, table_data_size is %lu\n",
1777 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1778 "SEP Driver: num_table_entries is %lu\n", num_table_entries);
1780 /* print entries of the table (without info entry) */
1781 for (entries_count = 0;
1782 entries_count < num_table_entries;
1783 entries_count++, lli_table_ptr++) {
1784 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1785 "SEP Driver:lli_table_ptr address is %08lx\n",
1786 (unsigned long)lli_table_ptr);
1787 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1788 "SEP Driver:phys address is %08lx block size is %lu\n",
1789 lli_table_ptr->physical_address, lli_table_ptr->block_size);
1792 /* point to the info entry */
1795 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1796 "SEP Driver:phys lli_table_ptr->block_size is %lu\n",
1797 lli_table_ptr->block_size);
1798 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1799 "SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
1800 lli_table_ptr->physical_address);
1803 table_data_size = lli_table_ptr->block_size & 0xffffff;
1804 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1805 lli_table_ptr = (struct sep_lli_entry_t *)
1806 (lli_table_ptr->physical_address);
1808 DEBUG_PRINT_3(SEP_DEBUG_LEVEL_EXTENDED,
1809 "SEP Driver:phys table_data_size is %lu num_table_entries is \
1810 %lu lli_table_ptr is%lu\n",
1811 table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
1813 if ((unsigned long)lli_table_ptr != 0xffffffff)
1814 lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
1815 (unsigned long)lli_table_ptr);
1820 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1821 "SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1826 This function locks all the physical pages of the application virtual buffer
1827 and construct a basic lli array, where each entry holds the physical page
1828 address and the size that application data holds in this physical pages
1830 int sep_lock_user_pages(unsigned long app_virt_addr,
1831 unsigned long data_size,
1832 unsigned long *num_pages_ptr,
1833 struct sep_lli_entry_t **lli_array_ptr,
1834 struct page ***page_array_ptr)
1840 /* the the page of the end address of the user space buffer */
1841 unsigned long end_page;
1843 /* the page of the start address of the user space buffer */
1844 unsigned long start_page;
1846 /* the range in pages */
1847 unsigned long num_pages;
1849 /* array of pointers ot page */
1850 struct page **page_array;
1853 struct sep_lli_entry_t *lli_array;
1856 unsigned long count;
1861 /*------------------------
1863 --------------------------*/
1865 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1866 "SEP Driver:--------> sep_lock_user_pages start\n");
1870 /* set start and end pages and num pages */
1871 end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1872 start_page = app_virt_addr >> PAGE_SHIFT;
1873 num_pages = end_page - start_page + 1;
1875 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1876 "SEP Driver: app_virt_addr is %08lx\n",
1878 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1879 "SEP Driver: data_size is %lu\n",
1881 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1882 "SEP Driver: start_page is %lu\n",
1884 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1885 "SEP Driver: end_page is %lu\n",
1887 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1888 "SEP Driver: num_pages is %lu\n",
1891 /* allocate array of pages structure pointers */
1892 page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1894 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1895 "SEP Driver: kmalloc for page_array failed\n");
1901 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1903 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1904 "SEP Driver: kmalloc for lli_array failed\n");
1907 goto end_function_with_error1;
1910 /* convert the application virtual address into a set of physical */
1911 down_read(¤t->mm->mmap_sem);
1912 result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
1915 up_read(¤t->mm->mmap_sem);
1917 /* check the number of pages locked - if not all then exit with error */
1918 if (result != num_pages) {
1919 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1920 "SEP Driver: not all pages locked by get_user_pages\n");
1923 goto end_function_with_error2;
1926 /* flush the cache */
1927 for (count = 0; count < num_pages; count++)
1928 flush_dcache_page(page_array[count]);
1930 /* set the start address of the first page - app data may start not at
1931 the beginning of the page */
1932 lli_array[0].physical_address = (
1933 (unsigned long)page_to_phys(page_array[0])) +
1934 (app_virt_addr & (~PAGE_MASK)) ;
1936 /* check that not all the data is in the first page only */
1937 if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1938 lli_array[0].block_size = data_size;
1940 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1943 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1944 "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
1945 lli_array[0].physical_address,
1946 lli_array[0].block_size);
1948 /* go from the second page to the prev before last */
1949 for (count = 1; count < (num_pages - 1); count++) {
1950 lli_array[count].physical_address =
1951 (unsigned long)page_to_phys(page_array[count]);
1952 lli_array[count].block_size = PAGE_SIZE;
1954 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1955 "lli_array[%lu].physical_address is %08lx, \
1956 lli_array[%lu].block_size is %lu\n",
1957 count, lli_array[count].physical_address,
1959 lli_array[count].block_size);
1962 /* if more then 1 pages locked - then update for the last page size needed */
1963 if (num_pages > 1) {
1964 /* update the address of the last page */
1965 lli_array[count].physical_address =
1966 (unsigned long)page_to_phys(page_array[count]);
1968 /* set the size of the last page */
1969 lli_array[count].block_size = (app_virt_addr + data_size) &
1972 if (lli_array[count].block_size == 0) {
1973 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1974 "app_virt_addr is %08lx\n",
1976 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
1979 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1980 "lli_array[%lu].physical_address is %08lx, \
1981 lli_array[%lu].block_size is %lu\n",
1982 count, lli_array[count].physical_address,
1984 lli_array[count].block_size);
1987 /* set output params */
1988 *lli_array_ptr = lli_array;
1989 *num_pages_ptr = num_pages;
1990 *page_array_ptr = page_array;
1994 end_function_with_error2:
1996 /* release the cache */
1997 for (count = 0; count < num_pages; count++)
1998 page_cache_release(page_array[count]);
2000 /* free lli array */
2003 end_function_with_error1:
2005 /* free page array */
2010 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2011 "SEP Driver:<-------- sep_lock_user_pages end\n");
2017 This function locks all the physical pages of the kernel virtual buffer
2018 and construct a basic lli array, where each entry holds the physical
2019 page address and the size that application data holds in this physical pages
2021 int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
2022 unsigned long data_size,
2023 unsigned long *num_pages_ptr,
2024 struct sep_lli_entry_t **lli_array_ptr,
2025 struct page ***page_array_ptr)
2031 /* the the page of the end address of the user space buffer */
2032 unsigned long end_page;
2034 /* the page of the start address of the user space buffer */
2035 unsigned long start_page;
2037 /* the range in pages */
2038 unsigned long num_pages;
2041 struct sep_lli_entry_t *lli_array;
2043 /* next kernel address to map */
2044 unsigned long next_kernel_address;
2047 unsigned long count;
2050 /*------------------------
2052 --------------------------*/
2054 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2055 "SEP Driver:--------> sep_lock_kernel_pages start\n");
2059 /* set start and end pages and num pages */
2060 end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
2061 start_page = kernel_virt_addr >> PAGE_SHIFT;
2062 num_pages = end_page - start_page + 1;
2064 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2065 "SEP Driver: kernel_virt_addr is %08lx\n",
2067 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2068 "SEP Driver: data_size is %lu\n",
2070 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2071 "SEP Driver: start_page is %lx\n",
2073 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2074 "SEP Driver: end_page is %lx\n",
2076 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2077 "SEP Driver: num_pages is %lu\n",
2080 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
2082 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
2083 "SEP Driver: kmalloc for lli_array failed\n");
2089 /* set the start address of the first page - app data may start not at
2090 the beginning of the page */
2091 lli_array[0].physical_address =
2092 (unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
2094 /* check that not all the data is in the first page only */
2095 if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
2096 lli_array[0].block_size = data_size;
2098 lli_array[0].block_size =
2099 PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
2102 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2103 "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
2104 lli_array[0].physical_address,
2105 lli_array[0].block_size);
2107 /* advance the address to the start of the next page */
2108 next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
2110 /* go from the second page to the prev before last */
2111 for (count = 1; count < (num_pages - 1); count++) {
2112 lli_array[count].physical_address =
2113 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2114 lli_array[count].block_size = PAGE_SIZE;
2116 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2117 "lli_array[%lu].physical_address is %08lx, \
2118 lli_array[%lu].block_size is %lu\n",
2119 count, lli_array[count].physical_address, count,
2120 lli_array[count].block_size);
2122 next_kernel_address += PAGE_SIZE;
2125 /* if more then 1 pages locked - then update for the last page size needed */
2126 if (num_pages > 1) {
2127 /* update the address of the last page */
2128 lli_array[count].physical_address =
2129 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2131 /* set the size of the last page */
2132 lli_array[count].block_size =
2133 (kernel_virt_addr + data_size) & (~PAGE_MASK);
2135 if (lli_array[count].block_size == 0) {
2136 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
2137 "app_virt_addr is %08lx\n",
2139 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
2143 DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2144 "lli_array[%lu].physical_address is %08lx, \
2145 lli_array[%lu].block_size is %lu\n",
2146 count, lli_array[count].physical_address,
2148 lli_array[count].block_size);
2151 /* set output params */
2152 *lli_array_ptr = lli_array;
2153 *num_pages_ptr = num_pages;
2154 *page_array_ptr = 0;
2159 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2160 "SEP Driver:<-------- sep_lock_kernel_pages end\n");
2166 This function releases all the application virtual buffer physical pages,
2167 that were previously locked
2169 int sep_free_dma_pages(struct page **page_array_ptr,
2170 unsigned long num_pages,
2171 unsigned long dirtyFlag)
2174 unsigned long count;
2176 /*-------------------
2178 ---------------------*/
2181 for (count = 0; count < num_pages; count++) {
2182 /* the out array was written, therefore the data was changed */
2183 if (!PageReserved(page_array_ptr[count]))
2184 SetPageDirty(page_array_ptr[count]);
2185 page_cache_release(page_array_ptr[count]);
2188 /* free in pages - the data was only read, therefore no update was done
2190 for (count = 0; count < num_pages; count++)
2191 page_cache_release(page_array_ptr[count]);
2195 /* free the array */
2196 kfree(page_array_ptr);
2202 This function raises interrupt to SEP that signals that is has a new
2205 static void sep_send_command_handler()
2208 unsigned long count;
2210 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2211 "SEP Driver:--------> sep_send_command_handler start\n");
2218 for (count = 0; count < 12 * 4; count += 4)
2219 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2220 "Word %lu of the message is %lu\n",
2222 *((unsigned long *)(sep_dev->shared_area_addr + count)));
2224 /* update counter */
2225 sep_dev->host_to_sep_send_counter++;
2227 /* send interrupt to SEP */
2228 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2230 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2231 "SEP Driver:<-------- sep_send_command_handler end\n");
2237 This function raises interrupt to SEPm that signals that is has a
2238 new command from HOST
2240 static void sep_send_reply_command_handler()
2242 unsigned long count;
2244 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2245 "SEP Driver:--------> sep_send_reply_command_handler start\n");
2250 for (count = 0; count < 12 * 4; count += 4)
2251 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2252 "Word %lu of the message is %lu\n",
2254 *((unsigned long *)(sep_dev->shared_area_addr + count)));
2257 /* update counter */
2258 sep_dev->host_to_sep_send_counter++;
2260 /* send the interrupt to SEP */
2261 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR,
2262 sep_dev->host_to_sep_send_counter);
2264 /* update both counters */
2265 sep_dev->host_to_sep_send_counter++;
2267 sep_dev->sep_to_host_reply_counter++;
2269 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2270 "SEP Driver:<-------- sep_send_reply_command_handler end\n");
2278 This function handles the allocate data pool memory request
2279 This function returns calculates the physical address of the
2280 allocated memory, and the offset of this area from the mapped address.
2281 Therefore, the FVOs in user space can calculate the exact virtual
2282 address of this allocated memory
2284 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
2289 /* command paramaters */
2290 struct sep_driver_alloc_t command_args;
2292 /*-------------------------
2294 ----------------------------*/
2296 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2297 "SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
2300 error = copy_from_user(&command_args,
2302 sizeof(struct sep_driver_alloc_t));
2306 /* allocate memory */
2308 (sep_dev->data_pool_bytes_allocated + command_args.num_bytes) >
2309 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
2314 /* set the virtual and physical address */
2315 command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2316 sep_dev->data_pool_bytes_allocated;
2317 command_args.phys_address = sep_dev->phys_shared_area_addr +
2318 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2319 sep_dev->data_pool_bytes_allocated;
2321 /* write the memory back to the user space */
2322 error = copy_to_user((void *)arg,
2323 (void *)&command_args,
2324 sizeof(struct sep_driver_alloc_t));
2328 /* set the allocation */
2329 sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
2333 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2334 "SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
2340 This function handles write into allocated data pool command
2342 static int sep_write_into_data_pool_handler(unsigned long arg)
2347 /* virtual address */
2348 unsigned long virt_address;
2350 /* application in address */
2351 unsigned long app_in_address;
2353 /* number of bytes */
2354 unsigned long num_bytes;
2356 /* address of the data pool */
2357 unsigned long data_pool_area_addr;
2359 /*--------------------------
2361 -----------------------------*/
2363 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2364 "SEP Driver:--------> sep_write_into_data_pool_handler start\n");
2366 /* get the application address */
2367 error = get_user(app_in_address,
2368 &(((struct sep_driver_write_t *)arg)->app_address));
2372 /* get the virtual kernel address address */
2373 error = get_user(virt_address,
2374 &(((struct sep_driver_write_t *)arg)->datapool_address));
2378 /* get the number of bytes */
2379 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2383 /* calculate the start of the data pool */
2384 data_pool_area_addr = sep_dev->shared_area_addr +
2385 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2388 /* check that the range of the virtual kernel address is correct */
2389 if ((virt_address < data_pool_area_addr) ||
2390 (virt_address > (data_pool_area_addr +
2391 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2396 /* copy the application data */
2397 error = copy_from_user((void *)virt_address,
2398 (void *)app_in_address,
2403 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2404 "SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
2410 this function handles the read from data pool command
2412 static int sep_read_from_data_pool_handler(unsigned long arg)
2417 /* virtual address of dest application buffer */
2418 unsigned long app_out_address;
2420 /* virtual address of the data pool */
2421 unsigned long virt_address;
2424 unsigned long num_bytes;
2426 /* address of the data pool */
2427 unsigned long data_pool_area_addr;
2429 /*------------------------
2431 -----------------------------*/
2433 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2434 "SEP Driver:--------> sep_read_from_data_pool_handler start\n");
2436 /* get the application address */
2437 error = get_user(app_out_address,
2438 &(((struct sep_driver_write_t *)arg)->app_address));
2442 /* get the virtual kernel address address */
2443 error = get_user(virt_address,
2444 &(((struct sep_driver_write_t *)arg)->datapool_address));
2448 /* get the number of bytes */
2449 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2453 /* calculate the start of the data pool */
2454 data_pool_area_addr = sep_dev->shared_area_addr +
2455 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2457 /* check that the range of the virtual kernel address is correct */
2458 if ((virt_address < data_pool_area_addr) ||
2459 (virt_address > (data_pool_area_addr +
2460 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2465 /* copy the application data */
2466 error = copy_to_user((void *)app_out_address, (void *)virt_address,
2471 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2472 "SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
2479 this function handles tha request for creation of the DMA table
2480 for the synchronic symmetric operations (AES,DES)
2482 static int sep_create_sync_dma_tables_handler(unsigned long arg)
2487 /* command arguments */
2488 struct sep_driver_build_sync_table_t command_args;
2490 /*------------------------
2492 --------------------------*/
2494 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2495 "SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
2497 error = copy_from_user(&command_args,
2499 sizeof(struct sep_driver_build_sync_table_t));
2503 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2504 "app_in_address is %08lx\n",
2505 command_args.app_in_address);
2506 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2507 "app_out_address is %08lx\n",
2508 command_args.app_out_address);
2509 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2510 "data_size is %lu\n",
2511 command_args.data_in_size);
2512 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2513 "block_size is %lu\n",
2514 command_args.block_size);
2517 /* check if we need to build only input table or input/output */
2518 if (command_args.app_out_address)
2519 /* prepare input and output tables */
2520 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
2521 command_args.app_out_address,
2522 command_args.data_in_size,
2523 command_args.block_size,
2524 &command_args.in_table_address,
2525 &command_args.out_table_address,
2526 &command_args.in_table_num_entries,
2527 &command_args.out_table_num_entries,
2528 &command_args.table_data_size,
2529 command_args.isKernelVirtualAddress);
2531 /* prepare input tables */
2532 error = sep_prepare_input_dma_table(command_args.app_in_address,
2533 command_args.data_in_size,
2534 command_args.block_size,
2535 &command_args.in_table_address,
2536 &command_args.in_table_num_entries,
2537 &command_args.table_data_size,
2538 command_args.isKernelVirtualAddress);
2544 error = copy_to_user((void *)arg,
2545 (void *)&command_args,
2546 sizeof(struct sep_driver_build_sync_table_t));
2550 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2551 "SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
2557 this function handles the request for freeing dma table for synhronic actions
2559 int sep_free_dma_table_data_handler()
2561 /*-------------------------
2563 -----------------------------*/
2565 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2566 "SEP Driver:--------> sep_free_dma_table_data_handler start\n");
2568 /* free input pages array */
2569 sep_free_dma_pages(sep_dev->in_page_array,
2570 sep_dev->in_num_pages,
2573 /* free output pages array if needed */
2574 if (sep_dev->out_page_array)
2575 sep_free_dma_pages(sep_dev->out_page_array,
2576 sep_dev->out_num_pages,
2579 /* reset all the values */
2580 sep_dev->in_page_array = 0;
2581 sep_dev->out_page_array = 0;
2582 sep_dev->in_num_pages = 0;
2583 sep_dev->out_num_pages = 0;
2586 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2587 "SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
2593 this function handles the request to create the DMA tables for flow
2595 static int sep_create_flow_dma_tables_handler(unsigned long arg)
2600 /* command arguments */
2601 struct sep_driver_build_flow_table_t command_args;
2603 /* first table - output */
2604 struct sep_lli_entry_t first_table_data;
2606 /* dma table data */
2607 struct sep_lli_entry_t last_table_data;
2609 /* pointer to the info entry of the previuos DMA table */
2610 struct sep_lli_entry_t *prev_info_entry_ptr;
2612 /* pointer to the flow data strucutre */
2613 struct sep_flow_context_t *flow_context_ptr;
2615 /*------------------------
2617 --------------------------*/
2619 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2620 "SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
2622 /* init variables */
2623 prev_info_entry_ptr = 0;
2624 first_table_data.physical_address = 0xffffffff;
2626 /* find the free structure for flow data */
2627 error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
2631 error = copy_from_user(&command_args,
2633 sizeof(struct sep_driver_build_flow_table_t));
2637 /* create flow tables */
2638 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2639 command_args.virt_buff_data_addr,
2643 command_args.isKernelVirtualAddress);
2645 goto end_function_with_error;
2647 /* check if flow is static */
2648 if (!command_args.flow_type)
2649 /* point the info entry of the last to the info entry of the first */
2650 last_table_data = first_table_data;
2652 /* set output params */
2653 command_args.first_table_addr = first_table_data.physical_address;
2654 command_args.first_table_num_entries =
2655 ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
2656 SEP_NUM_ENTRIES_MASK);
2657 command_args.first_table_data_size =
2658 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2660 /* send the parameters to user application */
2661 error = copy_to_user((void *)arg,
2663 sizeof(struct sep_driver_build_flow_table_t));
2665 goto end_function_with_error;
2667 /* all the flow created - update the flow entry with temp id */
2668 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
2670 /* set the processing tables data in the context */
2671 if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
2672 flow_context_ptr->input_tables_in_process = first_table_data;
2674 flow_context_ptr->output_tables_in_process = first_table_data;
2678 end_function_with_error:
2680 /* free the allocated tables */
2681 sep_deallocated_flow_tables(&first_table_data);
2685 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2686 "SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
2693 this functio n handles add tables to flow
2695 static int sep_add_flow_tables_handler(unsigned long arg)
2700 /* number of entries */
2701 unsigned long num_entries;
2703 /* command arguments */
2704 struct sep_driver_add_flow_table_t command_args;
2706 /* pointer to the flow data strucutre */
2707 struct sep_flow_context_t *flow_context_ptr;
2709 /* first dma table data */
2710 struct sep_lli_entry_t first_table_data;
2712 /* last dma table data */
2713 struct sep_lli_entry_t last_table_data;
2715 /* pointer to the info entry of the current DMA table */
2716 struct sep_lli_entry_t *info_entry_ptr;
2718 /*--------------------------
2720 ----------------------------*/
2722 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2723 "SEP Driver:--------> sep_add_flow_tables_handler start\n");
2725 /* get input parameters */
2726 error = copy_from_user(&command_args,
2728 sizeof(struct sep_driver_add_flow_table_t));
2732 /* find the flow structure for the flow id */
2733 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2737 /* prepare the flow dma tables */
2738 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2739 command_args.virt_buff_data_addr,
2743 command_args.isKernelVirtualAddress);
2745 goto end_function_with_error;
2747 /* now check if there is already an existing add table for this flow */
2748 if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
2749 /* this buffer was for input buffers */
2750 if (flow_context_ptr->input_tables_flag) {
2751 /* add table already exists - add the new tables to the end
2753 num_entries = (flow_context_ptr->last_input_table.block_size >>
2754 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2757 (struct sep_lli_entry_t *)
2758 (flow_context_ptr->last_input_table.physical_address +
2759 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2761 /* connect to list of tables */
2762 *info_entry_ptr = first_table_data;
2764 /* set the first table data */
2765 first_table_data = flow_context_ptr->first_input_table;
2767 /* set the input flag */
2768 flow_context_ptr->input_tables_flag = 1;
2770 /* set the first table data */
2771 flow_context_ptr->first_input_table = first_table_data;
2773 /* set the last table data */
2774 flow_context_ptr->last_input_table = last_table_data;
2775 } else /* this is output tables */ {
2776 /* this buffer was for input buffers */
2777 if (flow_context_ptr->output_tables_flag) {
2778 /* add table already exists - add the new tables to
2779 the end of the previous */
2780 num_entries = (flow_context_ptr->last_output_table.block_size >>
2781 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2784 (struct sep_lli_entry_t *)
2785 (flow_context_ptr->last_output_table.physical_address +
2786 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2788 /* connect to list of tables */
2789 *info_entry_ptr = first_table_data;
2791 /* set the first table data */
2792 first_table_data = flow_context_ptr->first_output_table;
2794 /* set the input flag */
2795 flow_context_ptr->output_tables_flag = 1;
2797 /* set the first table data */
2798 flow_context_ptr->first_output_table = first_table_data;
2800 /* set the last table data */
2801 flow_context_ptr->last_output_table = last_table_data;
2804 /* set output params */
2805 command_args.first_table_addr = first_table_data.physical_address;
2806 command_args.first_table_num_entries = ((first_table_data.block_size >>
2807 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
2808 command_args.first_table_data_size =
2809 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2811 /* send the parameters to user application */
2812 error = copy_to_user((void *)arg,
2814 sizeof(struct sep_driver_add_flow_table_t));
2816 goto end_function_with_error;
2818 end_function_with_error:
2820 /* free the allocated tables */
2821 sep_deallocated_flow_tables(&first_table_data);
2825 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2826 "SEP Driver:<-------- sep_add_flow_tables_handler end\n");
2832 this function add the flow add message to the specific flow
2834 static int sep_add_flow_tables_message_handler(unsigned long arg)
2840 struct sep_driver_add_message_t command_args;
2843 struct sep_flow_context_t *flow_context_ptr;
2845 /*----------------------------
2847 ------------------------------*/
2849 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2850 "SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
2852 error = copy_from_user(&command_args,
2854 sizeof(struct sep_driver_add_message_t));
2859 if (command_args.message_size_in_bytes >
2860 SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
2865 /* find the flow context */
2866 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2870 /* copy the message into context */
2871 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
2873 error = copy_from_user(flow_context_ptr->message,
2874 (void *)command_args.message_address,
2875 command_args.message_size_in_bytes);
2880 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2881 "SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
2888 this function returns the physical and virtual addresses of the static pool
2890 static int sep_get_static_pool_addr_handler(unsigned long arg)
2895 /* command arguments */
2896 struct sep_driver_static_pool_addr_t command_args;
2898 /*-----------------------------
2900 ------------------------------*/
2902 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2903 "SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2905 /*prepare the output parameters in the struct */
2906 command_args.physical_static_address = sep_dev->phys_shared_area_addr +
2907 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2908 command_args.virtual_static_address = sep_dev->shared_area_addr +
2909 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2911 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2912 "SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
2913 command_args.physical_static_address,
2914 command_args.virtual_static_address);
2916 /* send the parameters to user application */
2917 error = copy_to_user((void *)arg,
2919 sizeof(struct sep_driver_static_pool_addr_t));
2925 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2926 "SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2932 this address gets the offset of the physical address from the start
2935 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2940 /* command arguments */
2941 struct sep_driver_get_mapped_offset_t command_args;
2943 /*-----------------------------
2945 ------------------------------*/
2947 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2948 "SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2950 error = copy_from_user(&command_args,
2952 sizeof(struct sep_driver_get_mapped_offset_t));
2956 if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2961 /*prepare the output parameters in the struct */
2962 command_args.offset = command_args.physical_address -
2963 sep_dev->phys_shared_area_addr;
2965 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2966 "SEP Driver:physical_address is %08lx, offset is %lu\n",
2967 command_args.physical_address,
2968 command_args.offset);
2970 /* send the parameters to user application */
2971 error = copy_to_user((void *)arg,
2973 sizeof(struct sep_driver_get_mapped_offset_t));
2979 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2980 "SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2989 static int sep_start_handler(void)
2992 unsigned long reg_val;
2995 unsigned long error;
2997 /*-----------------------------
2999 ------------------------------*/
3001 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3002 "SEP Driver:--------> sep_start_handler start\n");
3006 /* wait in polling for message from SEP */
3008 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
3011 /* check the value */
3012 if (reg_val == 0x1) {
3013 /* fatal error - read erro status from GPRO */
3014 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
3020 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3021 "SEP Driver:<-------- sep_start_handler end\n");
3027 this function handles the request for SEP initialization
3029 static int sep_init_handler(unsigned long arg)
3031 /* word from message */
3032 unsigned long message_word;
3035 unsigned long *message_ptr;
3037 /* command arguments */
3038 struct sep_driver_init_t command_args;
3041 unsigned long counter;
3044 unsigned long error;
3047 unsigned long reg_val;
3049 /*-------------------
3051 ---------------------*/
3053 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3054 "SEP Driver:--------> sep_init_handler start\n");
3058 error = copy_from_user(&command_args, (void *)arg,
3059 sizeof(struct sep_driver_init_t));
3061 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3062 "SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
3067 /* PATCH - configure the DMA to single -burst instead of multi-burst */
3068 /*sep_configure_dma_burst();*/
3070 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3071 "SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
3073 message_ptr = (unsigned long *)command_args.message_addr;
3075 /* set the base address of the SRAM */
3076 sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
3079 counter < command_args.message_size_in_words;
3080 counter++, message_ptr++) {
3081 get_user(message_word, message_ptr);
3083 /* write data to SRAM */
3084 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR,
3087 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3088 "SEP Driver:message_word is %lu\n",
3091 /* wait for write complete */
3092 sep_wait_sram_write(sep_dev);
3095 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3096 "SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
3099 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR,
3103 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
3104 } while (!(reg_val & 0xFFFFFFFD));
3106 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3107 "SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
3109 /* check the value */
3110 if (reg_val == 0x1) {
3111 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
3112 "SEP Driver:init failed\n");
3114 error = sep_read_reg(sep_dev, 0x8060);
3115 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3116 "SEP Driver:sw monitor is %lu\n",
3119 /* fatal error - read erro status from GPRO */
3120 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
3121 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3122 "SEP Driver:error is %lu\n", error);
3128 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3129 "SEP Driver:<-------- sep_init_handler end\n");
3136 this function handles the request cache and resident reallocation
3138 static int sep_realloc_cache_resident_handler(unsigned long arg)
3143 /* physical cache addr */
3144 unsigned long phys_cache_address;
3146 /* physical resident addr */
3147 unsigned long phys_resident_address;
3149 /* command arguments */
3150 struct sep_driver_realloc_cache_resident_t command_args;
3152 /*------------------
3154 ---------------------*/
3157 error = copy_from_user(&command_args,
3159 sizeof(struct sep_driver_realloc_cache_resident_t));
3163 /* copy cache and resident to the their intended locations */
3164 error = sep_copy_cache_resident_to_area(command_args.cache_addr,
3165 command_args.cache_size_in_bytes,
3166 command_args.resident_addr,
3167 command_args.resident_size_in_bytes,
3168 &phys_cache_address,
3169 &phys_resident_address);
3173 /* lock the area (if needed) */
3174 sep_lock_cache_resident_area();
3176 command_args.new_base_addr = sep_dev->phys_shared_area_addr;
3178 /* find the new base address according to the lowest address between
3179 cache, resident and shared area */
3180 if (phys_resident_address < command_args.new_base_addr)
3181 command_args.new_base_addr = phys_resident_address;
3182 if (phys_cache_address < command_args.new_base_addr)
3183 command_args.new_base_addr = phys_cache_address;
3185 /* set the return parameters */
3186 command_args.new_cache_addr = phys_cache_address;
3187 command_args.new_resident_addr = phys_resident_address;
3190 /* set the new shared area */
3191 command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
3193 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3194 "SEP Driver:command_args.new_shared_area_addr is %08lx\n",
3195 command_args.new_shared_area_addr);
3196 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3197 "SEP Driver:command_args.new_base_addr is %08lx\n",
3198 command_args.new_base_addr);
3199 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3200 "SEP Driver:command_args.new_resident_addr is %08lx\n",
3201 command_args.new_resident_addr);
3202 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3203 "SEP Driver:command_args.new_cache_addr is %08lx\n",
3204 command_args.new_cache_addr);
3206 /* return to user */
3207 error = copy_to_user((void *)arg,
3208 (void *)&command_args,
3209 sizeof(struct sep_driver_realloc_cache_resident_t));
3217 this function handles the request for get time
3219 static int sep_get_time_handler(unsigned long arg)
3224 /* command arguments */
3225 struct sep_driver_get_time_t command_args;
3227 /*------------------------
3229 --------------------------*/
3231 error = sep_set_time(&command_args.time_physical_address,
3232 &command_args.time_value);
3234 /* return to user */
3235 error = copy_to_user((void *)arg,
3236 (void *)&command_args,
3237 sizeof(struct sep_driver_get_time_t));
3244 This api handles the setting of API mode to blocking or non-blocking
3246 static int sep_set_api_mode_handler(unsigned long arg)
3252 unsigned long mode_flag;
3254 /*----------------------------
3256 -----------------------------*/
3258 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3259 "SEP Driver:--------> sep_set_api_mode_handler start\n");
3262 mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
3266 /* set the global flag */
3267 sep_dev->block_mode_flag = mode_flag;
3272 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3273 "SEP Driver:<-------- sep_set_api_mode_handler end\n");
3279 This API handles the end transaction request
3281 static int sep_end_transaction_handler(unsigned long arg)
3283 /*----------------------------
3285 -----------------------------*/
3287 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3288 "SEP Driver:--------> sep_end_transaction_handler start\n");
3290 #if 0/*!SEP_DRIVER_POLLING_MODE*/
3292 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
3294 /* release IRQ line */
3295 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
3297 /* lock the sep mutex */
3298 mutex_unlock(&sep_mutex);
3301 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3302 "SEP Driver:<-------- sep_end_transaction_handler end\n");
3307 /* handler for flow done interrupt */
3308 static void sep_flow_done_handler(struct work_struct *work)
3310 /* flow context_ptr */
3311 struct sep_flow_context_t *flow_data_ptr;
3312 /*-------------------------
3314 ---------------------------*/
3316 /* obtain the mutex */
3317 mutex_lock(&sep_mutex);
3319 /* get the pointer to context */
3320 flow_data_ptr = (struct sep_flow_context_t *)work;
3322 /* free all the current input tables in sep */
3323 sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
3325 /* free all the current tables output tables in SEP (if needed) */
3326 if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
3327 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
3329 /* check if we have additional tables to be sent to SEP only input
3330 flag may be checked */
3331 if (flow_data_ptr->input_tables_flag) {
3332 /* copy the message to the shared RAM and signal SEP */
3333 memcpy((void *)flow_data_ptr->message,
3334 (void *)sep_dev->shared_area_addr,
3335 flow_data_ptr->message_size_in_bytes);
3337 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
3339 mutex_unlock(&sep_mutex);
3344 This function creates a list of tables for flow and returns the data for
3345 the first and last tables of the list
3347 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
3348 unsigned long first_buff_addr,
3349 struct sep_flow_context_t *flow_data_ptr,
3350 struct sep_lli_entry_t *first_table_data_ptr,
3351 struct sep_lli_entry_t *last_table_data_ptr,
3352 bool isKernelVirtualAddress)
3357 /* virtaul address of one buffer */
3358 unsigned long virt_buff_addr;
3360 /* virtual size of one buffer */
3361 unsigned long virt_buff_size;
3363 /* table data for each created table */
3364 struct sep_lli_entry_t table_data;
3367 struct sep_lli_entry_t *info_entry_ptr;
3369 /* prevouis info entry */
3370 struct sep_lli_entry_t *prev_info_entry_ptr;
3375 /*-------------------------------
3377 ----------------------------------*/
3381 prev_info_entry_ptr = 0;
3383 /* init the first table to default */
3384 table_data.physical_address = 0xffffffff;
3385 first_table_data_ptr->physical_address = 0xffffffff;
3386 table_data.block_size = 0;
3388 for (i = 0; i < num_virtual_buffers; i++) {
3389 /* get the virtual buffer address */
3390 error = get_user(virt_buff_addr, &first_buff_addr);
3394 /* get the virtual buffer size */
3396 error = get_user(virt_buff_size, &first_buff_addr);
3400 /* advance the address to point to the next pair of address|size */
3403 /* now prepare the one flow LLI table from the data */
3404 error = sep_prepare_one_flow_dma_table(virt_buff_addr,
3409 isKernelVirtualAddress);
3414 /* if this is the first table - save it to return to the user
3416 *first_table_data_ptr = table_data;
3418 /* set the pointer to info entry */
3419 prev_info_entry_ptr = info_entry_ptr;
3421 /* not first table - the previous table info entry should
3423 prev_info_entry_ptr->block_size =
3424 (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
3425 (table_data.block_size);
3427 /* set the pointer to info entry */
3428 prev_info_entry_ptr = info_entry_ptr;
3432 /* set the last table data */
3433 *last_table_data_ptr = table_data;
3442 This function creates one DMA table for flow and returns its data,
3443 and pointer to its info entry
3445 static int sep_prepare_one_flow_dma_table(
3446 unsigned long virt_buff_addr,
3447 unsigned long virt_buff_size,
3448 struct sep_lli_entry_t *table_data,
3449 struct sep_lli_entry_t **info_entry_ptr,
3450 struct sep_flow_context_t *flow_data_ptr,
3451 bool isKernelVirtualAddress)
3456 /* the range in pages */
3457 unsigned long lli_array_size;
3459 /* array of pointers ot page */
3460 struct sep_lli_entry_t *lli_array;
3462 /* pointer to the entry in the dma table */
3463 struct sep_lli_entry_t *flow_dma_table_entry_ptr;
3465 /* address of the dma table */
3466 unsigned long *start_dma_table_ptr;
3468 /* total table data counter */
3469 unsigned long dma_table_data_count;
3471 /* pointer that will keep the pointer t the pages of the virtual buffer */
3472 struct page **page_array_ptr;
3475 unsigned long entry_count;
3477 /*-------------------------------
3479 ----------------------------------*/
3481 /* find the space for the new table */
3482 error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
3486 /* check if the pages are in Kernel Virtual Address layout */
3487 if (isKernelVirtualAddress == true)
3488 /* lock kernel buffer in the memory */
3489 error = sep_lock_kernel_pages(virt_buff_addr,
3495 /* lock user buffer in the memory */
3496 error = sep_lock_user_pages(virt_buff_addr,
3505 /* set the pointer to page array at the beginning of table - this table is
3506 now considered taken */
3507 *start_dma_table_ptr = lli_array_size;
3509 /* point to the place of the pages pointers of the table */
3510 start_dma_table_ptr++;
3512 /* set the pages pointer */
3513 *start_dma_table_ptr = (unsigned long)page_array_ptr;
3515 /* set the pointer to the first entry */
3516 flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
3518 /* now create the entries for table */
3519 for (dma_table_data_count = entry_count = 0;
3520 entry_count < lli_array_size;
3522 flow_dma_table_entry_ptr->physical_address =
3523 lli_array[entry_count].physical_address;
3525 flow_dma_table_entry_ptr->block_size =
3526 lli_array[entry_count].block_size;
3528 /* set the total data of a table */
3529 dma_table_data_count += lli_array[entry_count].block_size;
3531 flow_dma_table_entry_ptr++;
3534 /* set the physical address */
3535 table_data->physical_address = virt_to_phys(start_dma_table_ptr);
3537 /* set the num_entries and total data size */
3538 table_data->block_size = ((lli_array_size + 1) <<
3539 SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
3540 (dma_table_data_count);
3542 /* set the info entry */
3543 flow_dma_table_entry_ptr->physical_address = 0xffffffff;
3544 flow_dma_table_entry_ptr->block_size = 0;
3546 /* set the pointer to info entry */
3547 *info_entry_ptr = flow_dma_table_entry_ptr;
3549 /* the array of the lli entries */
3559 This function returns pointer to the flow data structure
3560 that conatins the given id
3562 static int sep_find_flow_context(
3563 unsigned long flow_id,
3564 struct sep_flow_context_t **flow_data_ptr)
3567 unsigned long count;
3572 /*-----------------------
3574 ---------------------------*/
3579 always search for flow with id default first - in case we
3580 already started working on the flow there can be no situation
3581 when 2 flows are with default flag
3583 for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
3584 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
3585 *flow_data_ptr = &sep_dev->flows_data_array[count];
3590 if (count == SEP_DRIVER_NUM_FLOWS)
3598 this function find a space for the new flow dma table
3600 static int sep_find_free_flow_dma_table_space(
3601 unsigned long **table_address_ptr)
3606 /* pointer to the id field of the flow dma table */
3607 unsigned long *start_table_ptr;
3609 /* start address of the flow dma area */
3610 unsigned long flow_dma_area_start_addr;
3612 /* end address of the flow dma area */
3613 unsigned long flow_dma_area_end_addr;
3615 /* maximum table size in words */
3616 unsigned long table_size_in_words;
3618 /*---------------------
3620 -----------------------*/
3624 /* find the start address of the flow DMA table area */
3625 flow_dma_area_start_addr = sep_dev->shared_area_addr +
3626 SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
3628 /* set end address of the flow table area */
3629 flow_dma_area_end_addr = flow_dma_area_start_addr +
3630 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
3632 /* set table size in words */
3633 table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
3634 (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
3636 /* set the pointer to the start address of DMA area */
3637 start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
3639 /* find the space for the next table */
3640 while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
3641 ((unsigned long)start_table_ptr <
3642 flow_dma_area_end_addr))
3643 start_table_ptr += table_size_in_words;
3645 /* check if we reached the end of floa tables area */
3646 if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
3649 *table_address_ptr = start_table_ptr;
3655 this function goes over all the flow tables connected to the given
3656 table and deallocate them
3658 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
3661 unsigned long *table_ptr;
3663 /* end address of the flow dma area */
3664 unsigned long num_entries;
3666 unsigned long num_pages;
3669 struct page **pages_ptr;
3671 /* maximum table size in words */
3672 struct sep_lli_entry_t *info_entry_ptr;
3674 /*-------------------------------
3676 ---------------------------------*/
3678 /* set the pointer to the first table */
3679 table_ptr = (unsigned long *)first_table_ptr->physical_address;
3681 /* set the num of entries */
3682 num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
3683 & SEP_NUM_ENTRIES_MASK;
3685 /* go over all the connected tables */
3686 while (*table_ptr != 0xffffffff) {
3687 /* get number of pages */
3688 num_pages = *(table_ptr - 2);
3690 /* get the pointer to the pages */
3691 pages_ptr = (struct page **)(*(table_ptr - 1));
3693 /* free the pages */
3694 sep_free_dma_pages(pages_ptr, num_pages, 1);
3696 /* goto to the info entry */
3697 info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
3700 table_ptr = (unsigned long *)info_entry_ptr->physical_address;
3701 num_entries = (info_entry_ptr->block_size >>
3702 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
3709 This function handler the set flow id command
3711 static int sep_set_flow_id_handler(unsigned long arg)
3717 unsigned long flow_id;
3719 /* pointer to flow data structre */
3720 struct sep_flow_context_t *flow_data_ptr;
3722 /*----------------------
3724 -----------------------*/
3726 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3727 "------------>SEP Driver: sep_set_flow_id_handler start\n");
3729 error = get_user(flow_id,
3730 &(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
3734 /* find the flow data structure that was just used for creating new flow
3735 - its id should be default */
3736 error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
3741 flow_data_ptr->flow_id = flow_id;
3745 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3746 "SEP Driver:<-------- sep_set_flow_id_handler end\n");
3754 calculates time and sets it at the predefined address
3756 static int sep_set_time(unsigned long *address_ptr,
3757 unsigned long *time_in_sec_ptr)
3760 struct timeval time;
3762 /* address of time in the kernel */
3763 unsigned long time_addr;
3766 /*------------------------
3768 --------------------------*/
3770 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3771 "SEP Driver:--------> sep_set_time start\n");
3774 do_gettimeofday(&time);
3776 /* set value in the SYSTEM MEMORY offset */
3777 time_addr = sep_dev->message_shared_area_addr +
3778 SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
3780 *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
3781 *(unsigned long *)(time_addr + 4) = time.tv_sec;
3783 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3784 "SEP Driver:time.tv_sec is %lu\n",
3786 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3787 "SEP Driver:time_addr is %lu\n",
3789 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3790 "SEP Driver:g_message_shared_area_addr is %lu\n",
3791 sep_dev->message_shared_area_addr);
3793 /* set the output parameters if needed */
3795 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
3797 if (time_in_sec_ptr)
3798 *time_in_sec_ptr = time.tv_sec;
3800 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3801 "SEP Driver:<-------- sep_set_time end\n");
3807 PATCH for configuring the DMA to single burst instead of multi-burst
3809 static void sep_configure_dma_burst(void)
3812 #define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL
3814 unsigned long regVal;
3816 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3817 "SEP Driver:<-------- sep_configure_dma_burst start \n");
3819 /* request access to registers from SEP */
3820 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
3822 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3823 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n");
3825 regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3827 regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3829 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3830 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n");
3832 /* set the DMA burst register to single burst*/
3833 sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
3835 /* release the sep busy */
3836 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
3837 regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3838 while (regVal != 0x0)
3839 regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3841 DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3842 "SEP Driver:<-------- sep_configure_dma_burst done \n");
3846 module_init(sep_init);
3847 module_exit(sep_exit);
3849 MODULE_LICENSE("GPL");