]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/sep/sep_main_mod.c
Staging: sep: first pass after indent
[mv-sheeva.git] / drivers / staging / sep / sep_main_mod.c
1 /*
2  *
3  *  sep_main_mod.c - Security Processor Driver main group of functions
4  *
5  *  Copyright(c) 2009 Intel Corporation. All rights reserved.
6  *  Copyright(c) 2009 Discretix. All rights reserved.
7  *
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)
11  *  any later version.
12  *
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
16  *  more details.
17  *
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.
21  *
22  *  CONTACTS:
23  *
24  *  Mark Allyn          mark.a.allyn@intel.com
25  *
26  *  CHANGES:
27  *
28  *  2009.06.26  Initial publish
29  *
30  */
31
32 #include <linux/init.h>
33 #include <linux/module.h>
34 #include <linux/fs.h>
35 #include <linux/cdev.h>
36 #include <linux/kdev_t.h>
37 #include <linux/mutex.h>
38 #include <linux/mm.h>
39 #include <linux/poll.h>
40 #include <linux/wait.h>
41 #include <asm/ioctl.h>
42 #include <linux/ioport.h>
43 #include <asm/io.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"
51 #include "sep_dev.h"
52
53 /*----------------------------------------
54         DEFINES
55 -----------------------------------------*/
56
57
58 #define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
59
60 /*--------------------------------------
61   TYPEDEFS
62   -----------------------------------------*/
63
64
65
66 /*--------------------------------------------
67         GLOBAL variables
68 --------------------------------------------*/
69
70 /* debug messages level */
71 INT_MODULE_PARM(sepDebug, 0x0);
72 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
73
74 /* major and minor device numbers */
75 static dev_t g_sep_device_number;
76
77 /* the files operations structure of the driver */
78 static struct file_operations g_sep_fops;
79
80 /* cdev struct of the driver */
81 static struct cdev g_sep_cdev;
82
83 /*
84   mutex for the access to the internals of the sep driver
85 */
86 static DEFINE_MUTEX(sep_mutex);
87
88
89 /* wait queue head (event) of the driver */
90 static DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
91
92
93
94 /*------------------------------------------------
95   PROTOTYPES
96 ---------------------------------------------------*/
97
98 /*
99   interrupt handler function
100 */
101 irqreturn_t sep_inthandler(int irq, void *dev_id);
102
103 /*
104   this function registers the driver to the file system
105 */
106 static int sep_register_driver_to_fs(void);
107
108 /*
109   this function unregisters driver from fs
110 */
111 static void sep_unregister_driver_from_fs(void);
112
113 /*
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
117 */
118 static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries);
119 /*
120   this functions builds ont lli table from the lli_array according to the
121   given size of data
122 */
123 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr, struct sep_lli_entry_t *lli_table_ptr, unsigned long *num_processed_entries_ptr, unsigned long *num_table_entries_ptr, unsigned long table_data_size);
124
125 /*
126   this function goes over the list of the print created tables and prints
127   all the data
128 */
129 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size);
130
131
132
133 /*
134   This function raises interrupt to SEPm that signals that is has a new
135   command from HOST
136 */
137 static void sep_send_command_handler(void);
138
139
140 /*
141   This function raises interrupt to SEP that signals that is has a
142   new reply from HOST
143 */
144 static void sep_send_reply_command_handler(void);
145
146 /*
147   This function handles the allocate data pool memory request
148   This function returns calculates the physical address of the allocated memory
149   and the offset of this area from the mapped address. Therefore, the FVOs in
150   user space can calculate the exact virtual address of this allocated memory
151 */
152 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
153
154
155 /*
156   This function  handles write into allocated data pool command
157 */
158 static int sep_write_into_data_pool_handler(unsigned long arg);
159
160 /*
161   this function handles the read from data pool command
162 */
163 static int sep_read_from_data_pool_handler(unsigned long arg);
164
165 /*
166   this function handles tha request for creation of the DMA table
167   for the synchronic symmetric operations (AES,DES)
168 */
169 static int sep_create_sync_dma_tables_handler(unsigned long arg);
170
171 /*
172   this function handles the request to create the DMA tables for flow
173 */
174 static int sep_create_flow_dma_tables_handler(unsigned long arg);
175
176 /*
177   This API handles the end transaction request
178 */
179 static int sep_end_transaction_handler(unsigned long arg);
180
181
182 /*
183   this function handles add tables to flow
184 */
185 static int sep_add_flow_tables_handler(unsigned long arg);
186
187 /*
188   this function add the flow add message to the specific flow
189 */
190 static int sep_add_flow_tables_message_handler(unsigned long arg);
191
192 /*
193   this function handles the request for SEP start
194 */
195 static int sep_start_handler(void);
196
197 /*
198   this function handles the request for SEP initialization
199 */
200 static int sep_init_handler(unsigned long arg);
201
202 /*
203   this function handles the request cache and resident reallocation
204 */
205 static int sep_realloc_cache_resident_handler(unsigned long arg);
206
207
208 /*
209   This api handles the setting of API mode to blocking or non-blocking
210 */
211 static int sep_set_api_mode_handler(unsigned long arg);
212
213 /* handler for flow done interrupt */
214 static void sep_flow_done_handler(struct work_struct *work);
215
216 /*
217   This function locks all the physical pages of the kernel virtual buffer
218   and construct a basic lli  array, where each entry holds the physical
219   page address and the size that application data holds in this physical pages
220 */
221 static int sep_lock_kernel_pages(unsigned long kernel_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr);
222
223 /*
224   This function creates one DMA table for flow and returns its data,
225   and pointer to its info entry
226 */
227 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr, unsigned long virt_buff_size, struct sep_lli_entry_t *table_data, struct sep_lli_entry_t **info_entry_ptr, struct sep_flow_context_t *flow_data_ptr, bool isKernelVirtualAddress);
228
229 /*
230   This function creates a list of tables for flow and returns the data for the
231   first and last tables of the list
232 */
233 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
234                                        unsigned long first_buff_addr, struct sep_flow_context_t *flow_data_ptr, struct sep_lli_entry_t *first_table_data_ptr, struct sep_lli_entry_t *last_table_data_ptr, bool isKernelVirtualAddress);
235
236 /*
237   this function find a space for the new flow dma table
238 */
239 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr);
240
241 /*
242   this function goes over all the flow tables connected to the given table and
243   deallocate them
244 */
245 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr);
246
247 /*
248   This function handler the set flow id command
249 */
250 static int sep_set_flow_id_handler(unsigned long arg);
251
252 /*
253   This function returns pointer to the  flow data structure
254   that conatins the given id
255 */
256 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr);
257
258
259 /*
260   this function returns the physical and virtual addresses of the static pool
261 */
262 static int sep_get_static_pool_addr_handler(unsigned long arg);
263
264 /*
265   this address gets the offset of the physical address from the start of
266   the mapped area
267 */
268 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
269
270
271 /*
272   this function handles the request for get time
273 */
274 static int sep_get_time_handler(unsigned long arg);
275
276 /*
277   calculates time and sets it at the predefined address
278 */
279 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr);
280
281 /*
282   PATCH for configuring the DMA to single burst instead of multi-burst
283 */
284 static void sep_configure_dma_burst(void);
285
286 /*
287         This function locks all the physical pages of the
288         application virtual buffer and construct a basic lli
289         array, where each entry holds the physical page address
290         and the size that application data holds in this physical pages
291 */
292 static int sep_lock_user_pages(unsigned long app_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr);
293
294 /*---------------------------------------------
295         FUNCTIONS
296 -----------------------------------------------*/
297
298 /*
299   this function locks SEP by locking the semaphore
300 */
301 int sep_lock()
302 {
303         mutex_lock(&sep_mutex);
304         return 0;
305 }
306
307 /*
308   this function unlocks SEP
309 */
310 void sep_unlock()
311 {
312         /* release mutex */
313         mutex_unlock(&sep_mutex);
314 }
315
316 /*
317   this function returns the address of the message shared area
318 */
319 void sep_map_shared_area(unsigned long *mappedAddr_ptr)
320 {
321         *mappedAddr_ptr = sep_dev->shared_area_addr;
322 }
323
324 /*
325   this function returns the address of the message shared area
326 */
327 void sep_send_msg_rdy_cmd()
328 {
329         sep_send_command_handler();
330 }
331
332 /* this functions frees all the resources that were allocated for the building
333 of the LLI DMA tables */
334 void sep_free_dma_resources()
335 {
336         sep_free_dma_table_data_handler();
337 }
338
339 /* poll(suspend), until reply from sep */
340 void sep_driver_poll()
341 {
342         unsigned long retVal = 0;
343
344 #ifdef SEP_DRIVER_POLLING_MODE
345
346         while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
347                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
348
349         sep_dev->sep_to_host_reply_counter++;
350 #else
351         /* poll, until reply from sep */
352         wait_event(g_sep_event, (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
353
354 #endif
355 }
356
357 /*----------------------------------------------------------------------
358   open function of the character driver - must only lock the mutex
359         must also release the memory data pool allocations
360 ------------------------------------------------------------------------*/
361 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
362 {
363         int error;
364
365         dbg("SEP Driver:--------> open start\n");
366
367         error = 0;
368
369         /* check the blocking mode */
370         if (sep_dev->block_mode_flag)
371                 /* lock mutex */
372                 mutex_lock(&sep_mutex);
373         else
374                 error = mutex_trylock(&sep_mutex);
375
376         /* check the error */
377         if (error) {
378                 edbg("SEP Driver: down_interruptible failed\n");
379
380                 goto end_function;
381         }
382
383         /* release data pool allocations */
384         sep_dev->data_pool_bytes_allocated = 0;
385
386 end_function:
387         dbg("SEP Driver:<-------- open end\n");
388         return error;
389 }
390
391
392
393
394 /*------------------------------------------------------------
395         release function
396 -------------------------------------------------------------*/
397 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
398 {
399         dbg("----------->SEP Driver: sep_release start\n");
400
401 #if 0                           /*!SEP_DRIVER_POLLING_MODE */
402         /* close IMR */
403         sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
404
405         /* release IRQ line */
406         free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
407
408 #endif
409
410         /* unlock the sep mutex */
411         mutex_unlock(&sep_mutex);
412
413         dbg("SEP Driver:<-------- sep_release end\n");
414
415         return 0;
416 }
417
418
419
420
421 /*---------------------------------------------------------------
422   map function - this functions maps the message shared area
423 -----------------------------------------------------------------*/
424 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
425 {
426         unsigned long phys_addr;
427
428         dbg("-------->SEP Driver: mmap start\n");
429
430         /* check that the size of the mapped range is as the size of the message
431            shared area */
432         if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
433                 edbg("SEP Driver mmap requested size is more than allowed\n");
434                 printk(KERN_WARNING "SEP Driver mmap requested size is more \
435                         than allowed\n");
436                 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
437                 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
438                 return -EAGAIN;
439         }
440
441         edbg("SEP Driver:g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
442
443         /* get physical address */
444         phys_addr = sep_dev->phys_shared_area_addr;
445
446         edbg("SEP Driver: phys_addr is %08lx\n", phys_addr);
447
448         if (remap_pfn_range(vma, vma->vm_start, phys_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
449                 edbg("SEP Driver remap_page_range failed\n");
450                 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
451                 return -EAGAIN;
452         }
453
454         dbg("SEP Driver:<-------- mmap end\n");
455
456         return 0;
457 }
458
459
460 /*-----------------------------------------------
461   poll function
462 *----------------------------------------------*/
463 static unsigned int sep_poll(struct file *filp, poll_table * wait)
464 {
465         unsigned long count;
466         unsigned int mask = 0;
467         unsigned long retVal = 0;       /* flow id */
468
469         dbg("---------->SEP Driver poll: start\n");
470
471
472 #if SEP_DRIVER_POLLING_MODE
473
474         while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
475                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
476
477                 for (count = 0; count < 10 * 4; count += 4)
478                         edbg("Poll Debug Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
479         }
480
481         sep_dev->sep_to_host_reply_counter++;
482 #else
483         /* add the event to the polling wait table */
484         poll_wait(filp, &g_sep_event, wait);
485
486 #endif
487
488         edbg("sep_dev->host_to_sep_send_counter is %lu\n", sep_dev->host_to_sep_send_counter);
489         edbg("sep_dev->sep_to_host_reply_counter is %lu\n", sep_dev->sep_to_host_reply_counter);
490
491         /* check if the data is ready */
492         if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
493                 for (count = 0; count < 12 * 4; count += 4)
494                         edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
495
496                 for (count = 0; count < 10 * 4; count += 4)
497                         edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + 0x1800 + count)));
498
499                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
500                 edbg("retVal is %lu\n", retVal);
501                 /* check if the this is sep reply or request */
502                 if (retVal >> 31) {
503                         edbg("SEP Driver: sep request in\n");
504                         /* request */
505                         mask |= POLLOUT | POLLWRNORM;
506                 } else {
507                         edbg("SEP Driver: sep reply in\n");
508                         mask |= POLLIN | POLLRDNORM;
509                 }
510         }
511         dbg("SEP Driver:<-------- poll exit\n");
512         return mask;
513 }
514
515
516 static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
517 {
518         int error = 0;
519
520         dbg("------------>SEP Driver: ioctl start\n");
521
522         edbg("SEP Driver: cmd is %x\n", cmd);
523
524         /* check that the command is for sep device */
525         if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
526                 error = -ENOTTY;
527
528         switch (cmd) {
529         case SEP_IOCSENDSEPCOMMAND:
530                 /* send command to SEP */
531                 sep_send_command_handler();
532                 edbg("SEP Driver: after sep_send_command_handler\n");
533                 break;
534         case SEP_IOCSENDSEPRPLYCOMMAND:
535                 /* send reply command to SEP */
536                 sep_send_reply_command_handler();
537                 break;
538         case SEP_IOCALLOCDATAPOLL:
539                 /* allocate data pool */
540                 error = sep_allocate_data_pool_memory_handler(arg);
541                 break;
542         case SEP_IOCWRITEDATAPOLL:
543                 /* write data into memory pool */
544                 error = sep_write_into_data_pool_handler(arg);
545                 break;
546         case SEP_IOCREADDATAPOLL:
547                 /* read data from data pool into application memory */
548                 error = sep_read_from_data_pool_handler(arg);
549                 break;
550         case SEP_IOCCREATESYMDMATABLE:
551                 /* create dma table for synhronic operation */
552                 error = sep_create_sync_dma_tables_handler(arg);
553                 break;
554         case SEP_IOCCREATEFLOWDMATABLE:
555                 /* create flow dma tables */
556                 error = sep_create_flow_dma_tables_handler(arg);
557                 break;
558         case SEP_IOCFREEDMATABLEDATA:
559                 /* free the pages */
560                 error = sep_free_dma_table_data_handler();
561                 break;
562         case SEP_IOCSETFLOWID:
563                 /* set flow id */
564                 error = sep_set_flow_id_handler(arg);
565                 break;
566         case SEP_IOCADDFLOWTABLE:
567                 /* add tables to the dynamic flow */
568                 error = sep_add_flow_tables_handler(arg);
569                 break;
570         case SEP_IOCADDFLOWMESSAGE:
571                 /* add message of add tables to flow */
572                 error = sep_add_flow_tables_message_handler(arg);
573                 break;
574         case SEP_IOCSEPSTART:
575                 /* start command to sep */
576                 error = sep_start_handler();
577                 break;
578         case SEP_IOCSEPINIT:
579                 /* init command to sep */
580                 error = sep_init_handler(arg);
581                 break;
582         case SEP_IOCSETAPIMODE:
583                 /* set non- blocking mode */
584                 error = sep_set_api_mode_handler(arg);
585                 break;
586         case SEP_IOCGETSTATICPOOLADDR:
587                 /* get the physical and virtual addresses of the static pool */
588                 error = sep_get_static_pool_addr_handler(arg);
589                 break;
590         case SEP_IOCENDTRANSACTION:
591                 error = sep_end_transaction_handler(arg);
592                 break;
593         case SEP_IOCREALLOCCACHERES:
594                 error = sep_realloc_cache_resident_handler(arg);
595                 break;
596         case SEP_IOCGETMAPPEDADDROFFSET:
597                 error = sep_get_physical_mapped_offset_handler(arg);
598                 break;
599         case SEP_IOCGETIME:
600                 error = sep_get_time_handler(arg);
601                 break;
602         default:
603                 error = -ENOTTY;
604                 break;
605         }
606         dbg("SEP Driver:<-------- ioctl end\n");
607         return error;
608 }
609
610
611 /*
612   this function registers the driver to the file system
613 */
614 static int sep_register_driver_to_fs(void)
615 {
616         int ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
617         if (ret_val) {
618                 edbg("sep_driver:major number allocation failed, retval is %d\n", ret_val);
619                 goto end_function;
620         }
621
622         /* set the files operations structure */
623         g_sep_fops.owner = THIS_MODULE;
624         g_sep_fops.ioctl = sep_ioctl;
625         g_sep_fops.poll = sep_poll;
626         g_sep_fops.open = sep_open;
627         g_sep_fops.release = sep_release;
628         g_sep_fops.mmap = sep_mmap;
629
630         /* init cdev */
631         cdev_init(&g_sep_cdev, &g_sep_fops);
632         g_sep_cdev.owner = THIS_MODULE;
633
634         /* register the driver with the kernel */
635         ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
636
637         if (ret_val) {
638                 edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val);
639                 goto end_function_unregister_devnum;
640         }
641
642         goto end_function;
643
644 end_function_unregister_devnum:
645
646         /* unregister dev numbers */
647         unregister_chrdev_region(g_sep_device_number, 1);
648
649 end_function:
650       return ret_val;
651 }
652
653 /*
654   this function unregisters driver from fs
655 */
656 static void sep_unregister_driver_from_fs(void)
657 {
658         cdev_del(&g_sep_cdev);
659         /* unregister dev numbers */
660         unregister_chrdev_region(g_sep_device_number, 1);
661 }
662
663 /*--------------------------------------------------------------
664   init function
665 ----------------------------------------------------------------*/
666 static int __init sep_init(void)
667 {
668         int ret_val = 0;
669         int counter;
670         int size;               /* size of memory for allocation */
671
672         dbg("SEP Driver:-------->Init start\n");
673         edbg("sep->shared_area_addr = %lx\n", (unsigned long) &sep_dev->shared_area_addr);
674
675         /* transaction counter that coordinates the transactions between SEP
676         and HOST */
677         sep_dev->host_to_sep_send_counter = 0;
678
679         /* counter for the messages from sep */
680         sep_dev->sep_to_host_reply_counter = 0;
681
682         /* counter for the number of bytes allocated in the pool
683         for the current transaction */
684         sep_dev->data_pool_bytes_allocated = 0;
685
686         /* set the starting mode to blocking */
687         sep_dev->block_mode_flag = 1;
688
689         ret_val = sep_register_driver_to_device();
690         if (ret_val) {
691                 edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val);
692                 goto end_function_unregister_from_fs;
693         }
694         /* calculate the total size for allocation */
695         size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
696             SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
697
698         /* allocate the shared area */
699         if (sep_map_and_alloc_shared_area(size, &sep_dev->shared_area_addr, &sep_dev->phys_shared_area_addr)) {
700                 ret_val = -ENOMEM;
701                 /* allocation failed */
702                 goto end_function_unmap_io_memory;
703         }
704         /* now set the memory regions */
705         sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
706
707         edbg("SEP Driver: g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
708
709 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
710         /* send the new SHARED MESSAGE AREA to the SEP */
711         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep_dev->phys_shared_area_addr);
712
713         /* poll for SEP response */
714         retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
715         while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
716                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
717
718         /* check the return value (register) */
719         if (retVal != sep_dev->phys_shared_area_addr) {
720                 ret_val = -ENOMEM;
721                 goto end_function_deallocate_message_area;
722         }
723 #endif
724         /* init the flow contextes */
725         for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
726                 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
727
728         sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
729         if (sep_dev->flow_wq_ptr == 0) {
730                 ret_val = -ENOMEM;
731                 edbg("sep_driver:flow queue creation failed\n");
732                 goto end_function_deallocate_sep_shared_area;
733         }
734         edbg("SEP Driver: create flow workqueue \n");
735
736         /* register driver to fs */
737         ret_val = sep_register_driver_to_fs();
738         if (ret_val)
739                 goto end_function_deallocate_sep_shared_area;
740         /* load the rom code */
741         sep_load_rom_code();
742         goto end_function;
743 end_function_unregister_from_fs:
744         /* unregister from fs */
745         sep_unregister_driver_from_fs();
746 end_function_deallocate_sep_shared_area:
747         /* de-allocate shared area */
748         sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
749 end_function_unmap_io_memory:
750         iounmap((void *) sep_dev->reg_base_address);
751         /* release io memory region */
752         release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
753 end_function:
754         dbg("SEP Driver:<-------- Init end\n");
755         return ret_val;
756 }
757
758
759 /*-------------------------------------------------------------
760   exit function
761 --------------------------------------------------------------*/
762 static void __exit sep_exit(void)
763 {
764         int size;
765
766         dbg("SEP Driver:--------> Exit start\n");
767
768         /* unregister from fs */
769         sep_unregister_driver_from_fs();
770         /* calculate the total size for de-allocation */
771         size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
772             SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
773         /* free shared area  */
774         sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
775         edbg("SEP Driver: free pages SEP SHARED AREA \n");
776         iounmap((void *) sep_dev->reg_base_address);
777         edbg("SEP Driver: iounmap \n");
778         /* release io memory region */
779         release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
780         edbg("SEP Driver: release_mem_region \n");
781         dbg("SEP Driver:<-------- Exit end\n");
782 }
783
784
785 /*
786   interrupt handler function
787 */
788 irqreturn_t sep_inthandler(int irq, void *dev_id)
789 {
790         irqreturn_t int_error;
791         unsigned long error;
792         unsigned long reg_val;
793         unsigned long flow_id;
794         struct sep_flow_context_t *flow_context_ptr;
795
796         int_error = IRQ_HANDLED;
797
798         /* read the IRR register to check if this is SEP interrupt */
799         reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
800         edbg("SEP Interrupt - reg is %08lx\n", reg_val);
801
802         /* check if this is the flow interrupt */
803         if (0 /*reg_val & (0x1 << 11) */ ) {
804                 /* read GPRO to find out the which flow is done */
805                 flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
806
807                 /* find the contex of the flow */
808                 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
809                 if (error)
810                         goto end_function_with_error;
811
812                 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
813
814                 /* queue the work */
815                 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
816
817         } else {
818                 /* check if this is reply interrupt from SEP */
819                 if (reg_val & (0x1 << 13)) {
820                         /* update the counter of reply messages */
821                         sep_dev->sep_to_host_reply_counter++;
822
823                         /* wake up the waiting process */
824                         wake_up(&g_sep_event);
825                 } else {
826                         int_error = IRQ_NONE;
827                         goto end_function;
828                 }
829         }
830 end_function_with_error:
831         /* clear the interrupt */
832         sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
833 end_function:
834         return int_error;
835 }
836
837
838 /*
839   This function prepares only input DMA table for synhronic symmetric
840   operations (HASH)
841 */
842 int sep_prepare_input_dma_table(unsigned long app_virt_addr, unsigned long data_size, unsigned long block_size, unsigned long *lli_table_ptr, unsigned long *num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress)
843 {
844         /* pointer to the info entry of the table - the last entry */
845         struct sep_lli_entry_t *info_entry_ptr;
846         /* array of pointers ot page */
847         struct sep_lli_entry_t *lli_array_ptr;
848         /* points to the first entry to be processed in the lli_in_array */
849         unsigned long current_entry;
850         /* num entries in the virtual buffer */
851         unsigned long sep_lli_entries;
852         /* lli table pointer */
853         struct sep_lli_entry_t *in_lli_table_ptr;
854         /* the total data in one table */
855         unsigned long table_data_size;
856         /* number of entries in lli table */
857         unsigned long num_entries_in_table;
858         /* next table address */
859         unsigned long lli_table_alloc_addr;
860         unsigned long result;
861
862         dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
863
864         edbg("SEP Driver:data_size is %lu\n", data_size);
865         edbg("SEP Driver:block_size is %lu\n", block_size);
866
867         /* initialize the pages pointers */
868         sep_dev->in_page_array = 0;
869         sep_dev->in_num_pages = 0;
870
871         if (data_size == 0) {
872                 /* special case  - created 2 entries table with zero data */
873                 in_lli_table_ptr = (struct sep_lli_entry_t *) (sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
874                 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
875                 in_lli_table_ptr->block_size = 0;
876
877                 in_lli_table_ptr++;
878                 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
879                 in_lli_table_ptr->block_size = 0;
880
881                 *lli_table_ptr = sep_dev->phys_shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
882                 *num_entries_ptr = 2;
883                 *table_data_size_ptr = 0;
884
885                 goto end_function;
886         }
887
888         /* check if the pages are in Kernel Virtual Address layout */
889         if (isKernelVirtualAddress == true)
890                 /* lock the pages of the kernel buffer and translate them to pages */
891                 result = sep_lock_kernel_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
892         else
893                 /* lock the pages of the user buffer and translate them to pages */
894                 result = sep_lock_user_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
895
896         if (result)
897                 return result;
898
899         edbg("SEP Driver:output sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
900
901         current_entry = 0;
902         info_entry_ptr = 0;
903         sep_lli_entries = sep_dev->in_num_pages;
904
905         /* initiate to point after the message area */
906         lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
907
908         /* loop till all the entries in in array are not processed */
909         while (current_entry < sep_lli_entries) {
910                 /* set the new input and output tables */
911                 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
912
913                 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
914
915                 /* calculate the maximum size of data for input table */
916                 table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry));
917
918                 /* now calculate the table size so that it will be module block size */
919                 table_data_size = (table_data_size / block_size) * block_size;
920
921                 edbg("SEP Driver:output table_data_size is %lu\n", table_data_size);
922
923                 /* construct input lli table */
924                 sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, &current_entry, &num_entries_in_table, table_data_size);
925
926                 if (info_entry_ptr == 0) {
927                         /* set the output parameters to physical addresses */
928                         *lli_table_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
929                         *num_entries_ptr = num_entries_in_table;
930                         *table_data_size_ptr = table_data_size;
931
932                         edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr);
933                 } else {
934                         /* update the info entry of the previous in table */
935                         info_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
936                         info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
937                 }
938
939                 /* save the pointer to the info entry of the current tables */
940                 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
941         }
942
943         /* print input tables */
944         sep_debug_print_lli_tables((struct sep_lli_entry_t *)
945                                    sep_shared_area_phys_to_virt(*lli_table_ptr), *num_entries_ptr, *table_data_size_ptr);
946
947         /* the array of the pages */
948         kfree(lli_array_ptr);
949 end_function:
950         dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
951         return 0;
952
953 }
954
955 /*
956   This function builds input and output DMA tables for synhronic
957   symmetric operations (AES, DES). It also checks that each table
958   is of the modular block size
959 */
960 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
961                                        unsigned long app_virt_out_addr,
962                                        unsigned long data_size,
963                                        unsigned long block_size,
964                                        unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress)
965 {
966         /* array of pointers of page */
967         struct sep_lli_entry_t *lli_in_array;
968         /* array of pointers of page */
969         struct sep_lli_entry_t *lli_out_array;
970         int result = 0;
971
972         dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
973
974         /* initialize the pages pointers */
975         sep_dev->in_page_array = 0;
976         sep_dev->out_page_array = 0;
977
978         /* check if the pages are in Kernel Virtual Address layout */
979         if (isKernelVirtualAddress == true) {
980                 /* lock the pages of the kernel buffer and translate them to pages */
981                 result = sep_lock_kernel_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
982                 if (result) {
983                         edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
984                         goto end_function;
985                 }
986         } else {
987                 /* lock the pages of the user buffer and translate them to pages */
988                 result = sep_lock_user_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
989                 if (result) {
990                         edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
991                         goto end_function;
992                 }
993         }
994
995         if (isKernelVirtualAddress == true) {
996                 result = sep_lock_kernel_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
997                 if (result) {
998                         edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
999                         goto end_function_with_error1;
1000                 }
1001         } else {
1002                 result = sep_lock_user_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
1003                 if (result) {
1004                         edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1005                         goto end_function_with_error1;
1006                 }
1007         }
1008         edbg("sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1009         edbg("sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1010         edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1011
1012
1013         /* call the fucntion that creates table from the lli arrays */
1014         result = sep_construct_dma_tables_from_lli(lli_in_array, sep_dev->in_num_pages, lli_out_array, sep_dev->out_num_pages, block_size, lli_table_in_ptr, lli_table_out_ptr, in_num_entries_ptr, out_num_entries_ptr, table_data_size_ptr);
1015         if (result) {
1016                 edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1017                 goto end_function_with_error2;
1018         }
1019
1020         /* fall through - free the lli entry arrays */
1021         dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr);
1022         dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr);
1023         dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr);
1024 end_function_with_error2:
1025         kfree(lli_out_array);
1026 end_function_with_error1:
1027         kfree(lli_in_array);
1028 end_function:
1029         dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result);
1030         return result;
1031
1032 }
1033
1034
1035 /*
1036  This function creates the input and output dma tables for
1037  symmetric operations (AES/DES) according to the block size from LLI arays
1038 */
1039 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
1040                                       unsigned long sep_in_lli_entries,
1041                                       struct sep_lli_entry_t *lli_out_array,
1042                                       unsigned long sep_out_lli_entries,
1043                                       unsigned long block_size, unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr)
1044 {
1045         /* points to the area where next lli table can be allocated */
1046         unsigned long lli_table_alloc_addr;
1047         /* input lli table */
1048         struct sep_lli_entry_t *in_lli_table_ptr;
1049         /* output lli table */
1050         struct sep_lli_entry_t *out_lli_table_ptr;
1051         /* pointer to the info entry of the table - the last entry */
1052         struct sep_lli_entry_t *info_in_entry_ptr;
1053         /* pointer to the info entry of the table - the last entry */
1054         struct sep_lli_entry_t *info_out_entry_ptr;
1055         /* points to the first entry to be processed in the lli_in_array */
1056         unsigned long current_in_entry;
1057         /* points to the first entry to be processed in the lli_out_array */
1058         unsigned long current_out_entry;
1059         /* max size of the input table */
1060         unsigned long in_table_data_size;
1061         /* max size of the output table */
1062         unsigned long out_table_data_size;
1063         /* flag te signifies if this is the first tables build from the arrays */
1064         unsigned long first_table_flag;
1065         /* the data size that should be in table */
1066         unsigned long table_data_size;
1067         /* number of etnries in the input table */
1068         unsigned long num_entries_in_table;
1069         /* number of etnries in the output table */
1070         unsigned long num_entries_out_table;
1071
1072         dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1073
1074         /* initiate to pint after the message area */
1075         lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1076
1077         current_in_entry = 0;
1078         current_out_entry = 0;
1079         first_table_flag = 1;
1080         info_in_entry_ptr = 0;
1081         info_out_entry_ptr = 0;
1082
1083         /* loop till all the entries in in array are not processed */
1084         while (current_in_entry < sep_in_lli_entries) {
1085                 /* set the new input and output tables */
1086                 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
1087
1088                 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1089
1090                 /* set the first output tables */
1091                 out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
1092
1093                 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1094
1095                 /* calculate the maximum size of data for input table */
1096                 in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry));
1097
1098                 /* calculate the maximum size of data for output table */
1099                 out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry));
1100
1101                 edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1102                 edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1103
1104                 /* check where the data is smallest */
1105                 table_data_size = in_table_data_size;
1106                 if (table_data_size > out_table_data_size)
1107                         table_data_size = out_table_data_size;
1108
1109                 /* now calculate the table size so that it will be module block size */
1110                 table_data_size = (table_data_size / block_size) * block_size;
1111
1112                 dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
1113
1114                 /* construct input lli table */
1115                 sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, &current_in_entry, &num_entries_in_table, table_data_size);
1116
1117                 /* construct output lli table */
1118                 sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, &current_out_entry, &num_entries_out_table, table_data_size);
1119
1120                 /* if info entry is null - this is the first table built */
1121                 if (info_in_entry_ptr == 0) {
1122                         /* set the output parameters to physical addresses */
1123                         *lli_table_in_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
1124                         *in_num_entries_ptr = num_entries_in_table;
1125                         *lli_table_out_ptr = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
1126                         *out_num_entries_ptr = num_entries_out_table;
1127                         *table_data_size_ptr = table_data_size;
1128
1129                         edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1130                         edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1131                 } else {
1132                         /* update the info entry of the previous in table */
1133                         info_in_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
1134                         info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
1135
1136                         /* update the info entry of the previous in table */
1137                         info_out_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
1138                         info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size);
1139                 }
1140
1141                 /* save the pointer to the info entry of the current tables */
1142                 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1143                 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1144
1145                 edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table);
1146                 edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr);
1147                 edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr);
1148         }
1149
1150         /* print input tables */
1151         sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1152                                    sep_shared_area_phys_to_virt(*lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr);
1153         /* print output tables */
1154         sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1155                                    sep_shared_area_phys_to_virt(*lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr);
1156         dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1157         return 0;
1158 }
1159
1160 /*
1161   this function calculates the size of data that can be inserted into the lli
1162   table from this array the condition is that either the table is full
1163   (all etnries are entered), or there are no more entries in the lli array
1164 */
1165 unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries)
1166 {
1167         unsigned long table_data_size = 0;
1168         unsigned long counter;
1169
1170         /* calculate the data in the out lli table if till we fill the whole
1171            table or till the data has ended */
1172         for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++)
1173                 table_data_size += lli_in_array_ptr[counter].block_size;
1174         return table_data_size;
1175 }
1176
1177 /*
1178   this functions builds ont lli table from the lli_array according to
1179   the given size of data
1180 */
1181 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr, struct sep_lli_entry_t *lli_table_ptr, unsigned long *num_processed_entries_ptr, unsigned long *num_table_entries_ptr, unsigned long table_data_size)
1182 {
1183         unsigned long curr_table_data_size;
1184         /* counter of lli array entry */
1185         unsigned long array_counter;
1186
1187         dbg("SEP Driver:--------> sep_build_lli_table start\n");
1188
1189         /* init currrent table data size and lli array entry counter */
1190         curr_table_data_size = 0;
1191         array_counter = 0;
1192         *num_table_entries_ptr = 1;
1193
1194         edbg("SEP Driver:table_data_size is %lu\n", table_data_size);
1195
1196         /* fill the table till table size reaches the needed amount */
1197         while (curr_table_data_size < table_data_size) {
1198                 /* update the number of entries in table */
1199                 (*num_table_entries_ptr)++;
1200
1201                 lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address;
1202                 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1203                 curr_table_data_size += lli_table_ptr->block_size;
1204
1205                 edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1206                 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1207                 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1208
1209                 /* check for overflow of the table data */
1210                 if (curr_table_data_size > table_data_size) {
1211                         edbg("SEP Driver:curr_table_data_size > table_data_size\n");
1212
1213                         /* update the size of block in the table */
1214                         lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1215
1216                         /* update the physical address in the lli array */
1217                         lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size;
1218
1219                         /* update the block size left in the lli array */
1220                         lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size);
1221                 } else
1222                         /* advance to the next entry in the lli_array */
1223                         array_counter++;
1224
1225                 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1226                 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1227
1228                 /* move to the next entry in table */
1229                 lli_table_ptr++;
1230         }
1231
1232         /* set the info entry to default */
1233         lli_table_ptr->physical_address = 0xffffffff;
1234         lli_table_ptr->block_size = 0;
1235
1236         edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1237         edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1238         edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1239
1240         /* set the output parameter */
1241         *num_processed_entries_ptr += array_counter;
1242
1243         edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr);
1244         dbg("SEP Driver:<-------- sep_build_lli_table end\n");
1245         return;
1246 }
1247
1248 /*
1249   this function goes over the list of the print created tables and
1250   prints all the data
1251 */
1252 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size)
1253 {
1254         unsigned long table_count;
1255         unsigned long entries_count;
1256
1257         dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
1258
1259         table_count = 1;
1260         while ((unsigned long) lli_table_ptr != 0xffffffff) {
1261                 edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size);
1262                 edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries);
1263
1264                 /* print entries of the table (without info entry) */
1265                 for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) {
1266                         edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr);
1267                         edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size);
1268                 }
1269
1270                 /* point to the info entry */
1271                 lli_table_ptr--;
1272
1273                 edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1274                 edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1275
1276
1277                 table_data_size = lli_table_ptr->block_size & 0xffffff;
1278                 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1279                 lli_table_ptr = (struct sep_lli_entry_t *)
1280                     (lli_table_ptr->physical_address);
1281
1282                 edbg("SEP Driver:phys table_data_size is %lu num_table_entries is %lu lli_table_ptr is%lu\n", table_data_size, num_table_entries, (unsigned long) lli_table_ptr);
1283
1284                 if ((unsigned long) lli_table_ptr != 0xffffffff)
1285                         lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_area_phys_to_virt((unsigned long) lli_table_ptr);
1286
1287                 table_count++;
1288         }
1289         dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1290 }
1291
1292
1293 /*
1294   This function locks all the physical pages of the application virtual buffer
1295   and construct a basic lli  array, where each entry holds the physical page
1296   address and the size that application data holds in this physical pages
1297 */
1298 int sep_lock_user_pages(unsigned long app_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr)
1299 {
1300         int error = 0;
1301         /* the the page of the end address of the user space buffer */
1302         unsigned long end_page;
1303         /* the page of the start address of the user space buffer */
1304         unsigned long start_page;
1305         /* the range in pages */
1306         unsigned long num_pages;
1307         struct page **page_array;
1308         struct sep_lli_entry_t *lli_array;
1309         unsigned long count;
1310         int result;
1311
1312         dbg("SEP Driver:--------> sep_lock_user_pages start\n");
1313
1314         /* set start and end pages  and num pages */
1315         end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1316         start_page = app_virt_addr >> PAGE_SHIFT;
1317         num_pages = end_page - start_page + 1;
1318
1319         edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr);
1320         edbg("SEP Driver: data_size is %lu\n", data_size);
1321         edbg("SEP Driver: start_page is %lu\n", start_page);
1322         edbg("SEP Driver: end_page is %lu\n", end_page);
1323         edbg("SEP Driver: num_pages is %lu\n", num_pages);
1324
1325         /* allocate array of pages structure pointers */
1326         page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1327         if (!page_array) {
1328                 edbg("SEP Driver: kmalloc for page_array failed\n");
1329
1330                 error = -ENOMEM;
1331                 goto end_function;
1332         }
1333
1334         lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1335         if (!lli_array) {
1336                 edbg("SEP Driver: kmalloc for lli_array failed\n");
1337
1338                 error = -ENOMEM;
1339                 goto end_function_with_error1;
1340         }
1341
1342         /* convert the application virtual address into a set of physical */
1343         down_read(&current->mm->mmap_sem);
1344         result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0);
1345         up_read(&current->mm->mmap_sem);
1346
1347         /* check the number of pages locked - if not all then exit with error */
1348         if (result != num_pages) {
1349                 dbg("SEP Driver: not all pages locked by get_user_pages\n");
1350
1351                 error = -ENOMEM;
1352                 goto end_function_with_error2;
1353         }
1354
1355         /* flush the cache */
1356         for (count = 0; count < num_pages; count++)
1357                 flush_dcache_page(page_array[count]);
1358
1359         /* set the start address of the first page - app data may start not at
1360            the beginning of the page */
1361         lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK));
1362
1363         /* check that not all the data is in the first page only */
1364         if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1365                 lli_array[0].block_size = data_size;
1366         else
1367                 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1368
1369         /* debug print */
1370         dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size);
1371
1372         /* go from the second page to the prev before last */
1373         for (count = 1; count < (num_pages - 1); count++) {
1374                 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
1375                 lli_array[count].block_size = PAGE_SIZE;
1376
1377                 edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1378         }
1379
1380         /* if more then 1 pages locked - then update for the last page size needed */
1381         if (num_pages > 1) {
1382                 /* update the address of the last page */
1383                 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
1384
1385                 /* set the size of the last page */
1386                 lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK);
1387
1388                 if (lli_array[count].block_size == 0) {
1389                         dbg("app_virt_addr is %08lx\n", app_virt_addr);
1390                         dbg("data_size is %lu\n", data_size);
1391                         while (1);
1392                 }
1393                 edbg("lli_array[%lu].physical_address is %08lx, \
1394                 lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1395         }
1396
1397         /* set output params */
1398         *lli_array_ptr = lli_array;
1399         *num_pages_ptr = num_pages;
1400         *page_array_ptr = page_array;
1401         goto end_function;
1402
1403 end_function_with_error2:
1404         /* release the cache */
1405         for (count = 0; count < num_pages; count++)
1406                 page_cache_release(page_array[count]);
1407         kfree(lli_array);
1408 end_function_with_error1:
1409         kfree(page_array);
1410 end_function:
1411         dbg("SEP Driver:<-------- sep_lock_user_pages end\n");
1412         return 0;
1413 }
1414
1415 /*
1416   This function locks all the physical pages of the kernel virtual buffer
1417   and construct a basic lli  array, where each entry holds the physical
1418   page address and the size that application data holds in this physical pages
1419 */
1420 int sep_lock_kernel_pages(unsigned long kernel_virt_addr, unsigned long data_size, unsigned long *num_pages_ptr, struct sep_lli_entry_t **lli_array_ptr, struct page ***page_array_ptr)
1421 {
1422         int error = 0;
1423         /* the the page of the end address of the user space buffer */
1424         unsigned long end_page;
1425         /* the page of the start address of the user space buffer */
1426         unsigned long start_page;
1427         /* the range in pages */
1428         unsigned long num_pages;
1429         struct sep_lli_entry_t *lli_array;
1430         /* next kernel address to map */
1431         unsigned long next_kernel_address;
1432         unsigned long count;
1433
1434         dbg("SEP Driver:--------> sep_lock_kernel_pages start\n");
1435
1436         /* set start and end pages  and num pages */
1437         end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
1438         start_page = kernel_virt_addr >> PAGE_SHIFT;
1439         num_pages = end_page - start_page + 1;
1440
1441         edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr);
1442         edbg("SEP Driver: data_size is %lu\n", data_size);
1443         edbg("SEP Driver: start_page is %lx\n", start_page);
1444         edbg("SEP Driver: end_page is %lx\n", end_page);
1445         edbg("SEP Driver: num_pages is %lu\n", num_pages);
1446
1447         lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1448         if (!lli_array) {
1449                 edbg("SEP Driver: kmalloc for lli_array failed\n");
1450                 error = -ENOMEM;
1451                 goto end_function;
1452         }
1453
1454         /* set the start address of the first page - app data may start not at
1455            the beginning of the page */
1456         lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr);
1457
1458         /* check that not all the data is in the first page only */
1459         if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
1460                 lli_array[0].block_size = data_size;
1461         else
1462                 lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
1463
1464         /* debug print */
1465         dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size);
1466
1467         /* advance the address to the start of the next page */
1468         next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
1469
1470         /* go from the second page to the prev before last */
1471         for (count = 1; count < (num_pages - 1); count++) {
1472                 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
1473                 lli_array[count].block_size = PAGE_SIZE;
1474
1475                 edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1476                 next_kernel_address += PAGE_SIZE;
1477         }
1478
1479         /* if more then 1 pages locked - then update for the last page size needed */
1480         if (num_pages > 1) {
1481                 /* update the address of the last page */
1482                 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
1483
1484                 /* set the size of the last page */
1485                 lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK);
1486
1487                 if (lli_array[count].block_size == 0) {
1488                         dbg("app_virt_addr is %08lx\n", kernel_virt_addr);
1489                         dbg("data_size is %lu\n", data_size);
1490                         while (1);
1491                 }
1492
1493                 edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1494         }
1495         /* set output params */
1496         *lli_array_ptr = lli_array;
1497         *num_pages_ptr = num_pages;
1498         *page_array_ptr = 0;
1499 end_function:
1500         dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n");
1501         return 0;
1502 }
1503
1504 /*
1505   This function releases all the application virtual buffer physical pages,
1506         that were previously locked
1507 */
1508 int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag)
1509 {
1510         unsigned long count;
1511
1512         if (dirtyFlag) {
1513                 for (count = 0; count < num_pages; count++) {
1514                         /* the out array was written, therefore the data was changed */
1515                         if (!PageReserved(page_array_ptr[count]))
1516                                 SetPageDirty(page_array_ptr[count]);
1517                         page_cache_release(page_array_ptr[count]);
1518                 }
1519         } else {
1520                 /* free in pages - the data was only read, therefore no update was done
1521                    on those pages */
1522                 for (count = 0; count < num_pages; count++)
1523                         page_cache_release(page_array_ptr[count]);
1524         }
1525
1526         if (page_array_ptr)
1527                 /* free the array */
1528                 kfree(page_array_ptr);
1529
1530         return 0;
1531 }
1532
1533 /*
1534   This function raises interrupt to SEP that signals that is has a new
1535         command from HOST
1536 */
1537 static void sep_send_command_handler()
1538 {
1539         unsigned long count;
1540
1541         dbg("SEP Driver:--------> sep_send_command_handler start\n");
1542         sep_set_time(0, 0);
1543
1544         /* flash cache */
1545         flush_cache_all();
1546
1547         for (count = 0; count < 12 * 4; count += 4)
1548                 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
1549
1550         /* update counter */
1551         sep_dev->host_to_sep_send_counter++;
1552         /* send interrupt to SEP */
1553         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
1554         dbg("SEP Driver:<-------- sep_send_command_handler end\n");
1555         return;
1556 }
1557
1558 /*
1559   This function raises interrupt to SEPm that signals that is has a
1560   new command from HOST
1561 */
1562 static void sep_send_reply_command_handler()
1563 {
1564         unsigned long count;
1565
1566         dbg("SEP Driver:--------> sep_send_reply_command_handler start\n");
1567
1568         /* flash cache */
1569         flush_cache_all();
1570         for (count = 0; count < 12 * 4; count += 4)
1571                 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
1572         /* update counter */
1573         sep_dev->host_to_sep_send_counter++;
1574         /* send the interrupt to SEP */
1575         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep_dev->host_to_sep_send_counter);
1576         /* update both counters */
1577         sep_dev->host_to_sep_send_counter++;
1578         sep_dev->sep_to_host_reply_counter++;
1579         dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n");
1580 }
1581
1582
1583
1584 /*
1585   This function handles the allocate data pool memory request
1586   This function returns calculates the physical address of the
1587   allocated memory, and the offset of this area from the mapped address.
1588   Therefore, the FVOs in user space can calculate the exact virtual
1589   address of this allocated memory
1590 */
1591 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
1592 {
1593         int error;
1594         struct sep_driver_alloc_t command_args;
1595
1596         dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
1597
1598         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
1599         if (error)
1600                 goto end_function;
1601
1602         /* allocate memory */
1603         if ((sep_dev->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
1604                 error = -ENOTTY;
1605                 goto end_function;
1606         }
1607
1608         /* set the virtual and physical address */
1609         command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
1610         command_args.phys_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
1611
1612         /* write the memory back to the user space */
1613         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
1614         if (error)
1615                 goto end_function;
1616
1617         /* set the allocation */
1618         sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
1619
1620 end_function:
1621         dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
1622         return error;
1623 }
1624
1625 /*
1626   This function  handles write into allocated data pool command
1627 */
1628 static int sep_write_into_data_pool_handler(unsigned long arg)
1629 {
1630         int error;
1631         unsigned long virt_address;
1632         unsigned long app_in_address;
1633         unsigned long num_bytes;
1634         unsigned long data_pool_area_addr;
1635
1636         dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n");
1637
1638         /* get the application address */
1639         error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address));
1640         if (error)
1641                 goto end_function;
1642
1643         /* get the virtual kernel address address */
1644         error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
1645         if (error)
1646                 goto end_function;
1647
1648         /* get the number of bytes */
1649         error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
1650         if (error)
1651                 goto end_function;
1652
1653         /* calculate the start of the data pool */
1654         data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
1655
1656
1657         /* check that the range of the virtual kernel address is correct */
1658         if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
1659                 error = -ENOTTY;
1660                 goto end_function;
1661         }
1662         /* copy the application data */
1663         error = copy_from_user((void *) virt_address, (void *) app_in_address, num_bytes);
1664 end_function:
1665         dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
1666         return error;
1667 }
1668
1669 /*
1670   this function handles the read from data pool command
1671 */
1672 static int sep_read_from_data_pool_handler(unsigned long arg)
1673 {
1674         int error;
1675         /* virtual address of dest application buffer */
1676         unsigned long app_out_address;
1677         /* virtual address of the data pool */
1678         unsigned long virt_address;
1679         unsigned long num_bytes;
1680         unsigned long data_pool_area_addr;
1681
1682         dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n");
1683
1684         /* get the application address */
1685         error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address));
1686         if (error)
1687                 goto end_function;
1688
1689         /* get the virtual kernel address address */
1690         error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
1691         if (error)
1692                 goto end_function;
1693
1694         /* get the number of bytes */
1695         error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
1696         if (error)
1697                 goto end_function;
1698
1699         /* calculate the start of the data pool */
1700         data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
1701
1702         /* check that the range of the virtual kernel address is correct */
1703         if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
1704                 error = -ENOTTY;
1705                 goto end_function;
1706         }
1707
1708         /* copy the application data */
1709         error = copy_to_user((void *) app_out_address, (void *) virt_address, num_bytes);
1710 end_function:
1711         dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
1712         return error;
1713 }
1714
1715
1716 /*
1717   this function handles tha request for creation of the DMA table
1718   for the synchronic symmetric operations (AES,DES)
1719 */
1720 static int sep_create_sync_dma_tables_handler(unsigned long arg)
1721 {
1722         int error;
1723         /* command arguments */
1724         struct sep_driver_build_sync_table_t command_args;
1725
1726         dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
1727
1728         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
1729         if (error)
1730                 goto end_function;
1731
1732         edbg("app_in_address is %08lx\n", command_args.app_in_address);
1733         edbg("app_out_address is %08lx\n", command_args.app_out_address);
1734         edbg("data_size is %lu\n", command_args.data_in_size);
1735         edbg("block_size is %lu\n", command_args.block_size);
1736
1737         /* check if we need to build only input table or input/output */
1738         if (command_args.app_out_address)
1739                 /* prepare input and output tables */
1740                 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
1741                                                            command_args.app_out_address,
1742                                                            command_args.data_in_size,
1743                                                            command_args.block_size,
1744                                                            &command_args.in_table_address,
1745                                                            &command_args.out_table_address, &command_args.in_table_num_entries, &command_args.out_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress);
1746         else
1747                 /* prepare input tables */
1748                 error = sep_prepare_input_dma_table(command_args.app_in_address,
1749                                                     command_args.data_in_size, command_args.block_size, &command_args.in_table_address, &command_args.in_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress);
1750
1751         if (error)
1752                 goto end_function;
1753         /* copy to user */
1754         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t));
1755 end_function:
1756         dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
1757         return error;
1758 }
1759
1760 /*
1761   this function handles the request for freeing dma table for synhronic actions
1762 */
1763 int sep_free_dma_table_data_handler()
1764 {
1765         dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
1766
1767         /* free input pages array */
1768         sep_free_dma_pages(sep_dev->in_page_array, sep_dev->in_num_pages, 0);
1769
1770         /* free output pages array if needed */
1771         if (sep_dev->out_page_array)
1772                 sep_free_dma_pages(sep_dev->out_page_array, sep_dev->out_num_pages, 1);
1773
1774         /* reset all the values */
1775         sep_dev->in_page_array = 0;
1776         sep_dev->out_page_array = 0;
1777         sep_dev->in_num_pages = 0;
1778         sep_dev->out_num_pages = 0;
1779         dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
1780         return 0;
1781 }
1782
1783 /*
1784   this function handles the request to create the DMA tables for flow
1785 */
1786 static int sep_create_flow_dma_tables_handler(unsigned long arg)
1787 {
1788         int error;
1789         struct sep_driver_build_flow_table_t command_args;
1790         /* first table - output */
1791         struct sep_lli_entry_t first_table_data;
1792         /* dma table data */
1793         struct sep_lli_entry_t last_table_data;
1794         /* pointer to the info entry of the previuos DMA table */
1795         struct sep_lli_entry_t *prev_info_entry_ptr;
1796         /* pointer to the flow data strucutre */
1797         struct sep_flow_context_t *flow_context_ptr;
1798
1799         dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
1800
1801         /* init variables */
1802         prev_info_entry_ptr = 0;
1803         first_table_data.physical_address = 0xffffffff;
1804
1805         /* find the free structure for flow data */
1806         error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
1807         if (error)
1808                 goto end_function;
1809
1810         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
1811         if (error)
1812                 goto end_function;
1813
1814         /* create flow tables */
1815         error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
1816         if (error)
1817                 goto end_function_with_error;
1818
1819         /* check if flow is static */
1820         if (!command_args.flow_type)
1821                 /* point the info entry of the last to the info entry of the first */
1822                 last_table_data = first_table_data;
1823
1824         /* set output params */
1825         command_args.first_table_addr = first_table_data.physical_address;
1826         command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1827         command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1828
1829         /* send the parameters to user application */
1830         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
1831         if (error)
1832                 goto end_function_with_error;
1833
1834         /* all the flow created  - update the flow entry with temp id */
1835         flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
1836
1837         /* set the processing tables data in the context */
1838         if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
1839                 flow_context_ptr->input_tables_in_process = first_table_data;
1840         else
1841                 flow_context_ptr->output_tables_in_process = first_table_data;
1842
1843         goto end_function;
1844
1845 end_function_with_error:
1846         /* free the allocated tables */
1847         sep_deallocated_flow_tables(&first_table_data);
1848 end_function:
1849         dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
1850         return error;
1851 }
1852
1853 /*
1854   this functio n handles add tables to flow
1855 */
1856 static int sep_add_flow_tables_handler(unsigned long arg)
1857 {
1858         int error;
1859         unsigned long num_entries;
1860         struct sep_driver_add_flow_table_t command_args;
1861         struct sep_flow_context_t *flow_context_ptr;
1862         /* first dma table data */
1863         struct sep_lli_entry_t first_table_data;
1864         /* last dma table data */
1865         struct sep_lli_entry_t last_table_data;
1866         /* pointer to the info entry of the current DMA table */
1867         struct sep_lli_entry_t *info_entry_ptr;
1868
1869         dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n");
1870
1871         /* get input parameters */
1872         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
1873         if (error)
1874                 goto end_function;
1875
1876         /* find the flow structure for the flow id */
1877         error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1878         if (error)
1879                 goto end_function;
1880
1881         /* prepare the flow dma tables */
1882         error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
1883         if (error)
1884                 goto end_function_with_error;
1885
1886         /* now check if there is already an existing add table for this flow */
1887         if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
1888                 /* this buffer was for input buffers */
1889                 if (flow_context_ptr->input_tables_flag) {
1890                         /* add table already exists - add the new tables to the end
1891                            of the previous */
1892                         num_entries = (flow_context_ptr->last_input_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1893
1894                         info_entry_ptr = (struct sep_lli_entry_t *)
1895                             (flow_context_ptr->last_input_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1896
1897                         /* connect to list of tables */
1898                         *info_entry_ptr = first_table_data;
1899
1900                         /* set the first table data */
1901                         first_table_data = flow_context_ptr->first_input_table;
1902                 } else {
1903                         /* set the input flag */
1904                         flow_context_ptr->input_tables_flag = 1;
1905
1906                         /* set the first table data */
1907                         flow_context_ptr->first_input_table = first_table_data;
1908                 }
1909                 /* set the last table data */
1910                 flow_context_ptr->last_input_table = last_table_data;
1911         } else {                /* this is output tables */
1912
1913                 /* this buffer was for input buffers */
1914                 if (flow_context_ptr->output_tables_flag) {
1915                         /* add table already exists - add the new tables to
1916                            the end of the previous */
1917                         num_entries = (flow_context_ptr->last_output_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1918
1919                         info_entry_ptr = (struct sep_lli_entry_t *)
1920                             (flow_context_ptr->last_output_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1921
1922                         /* connect to list of tables */
1923                         *info_entry_ptr = first_table_data;
1924
1925                         /* set the first table data */
1926                         first_table_data = flow_context_ptr->first_output_table;
1927                 } else {
1928                         /* set the input flag */
1929                         flow_context_ptr->output_tables_flag = 1;
1930
1931                         /* set the first table data */
1932                         flow_context_ptr->first_output_table = first_table_data;
1933                 }
1934                 /* set the last table data */
1935                 flow_context_ptr->last_output_table = last_table_data;
1936         }
1937
1938         /* set output params */
1939         command_args.first_table_addr = first_table_data.physical_address;
1940         command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1941         command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1942
1943         /* send the parameters to user application */
1944         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
1945         if (error)
1946                 goto end_function_with_error;
1947
1948 end_function_with_error:
1949         /* free the allocated tables */
1950         sep_deallocated_flow_tables(&first_table_data);
1951 end_function:
1952         dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
1953         return error;
1954 }
1955
1956 /*
1957   this function add the flow add message to the specific flow
1958 */
1959 static int sep_add_flow_tables_message_handler(unsigned long arg)
1960 {
1961         int error;
1962         struct sep_driver_add_message_t command_args;
1963         struct sep_flow_context_t *flow_context_ptr;
1964
1965         dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
1966
1967         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
1968         if (error)
1969                 goto end_function;
1970
1971         /* check input */
1972         if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
1973                 error = -ENOMEM;
1974                 goto end_function;
1975         }
1976
1977         /* find the flow context */
1978         error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1979         if (error)
1980                 goto end_function;
1981
1982         /* copy the message into context */
1983         flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
1984         error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
1985 end_function:
1986         dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
1987         return error;
1988 }
1989
1990
1991 /*
1992   this function returns the physical and virtual addresses of the static pool
1993 */
1994 static int sep_get_static_pool_addr_handler(unsigned long arg)
1995 {
1996         int error;
1997         struct sep_driver_static_pool_addr_t command_args;
1998
1999         dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2000
2001         /*prepare the output parameters in the struct */
2002         command_args.physical_static_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2003         command_args.virtual_static_address = sep_dev->shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2004
2005         edbg("SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
2006
2007         /* send the parameters to user application */
2008         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
2009         if (error)
2010                 goto end_function;
2011 end_function:
2012         dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2013         return error;
2014 }
2015
2016 /*
2017   this address gets the offset of the physical address from the start
2018   of the mapped area
2019 */
2020 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2021 {
2022         int error;
2023         struct sep_driver_get_mapped_offset_t command_args;
2024
2025         dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2026
2027         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
2028         if (error)
2029                 goto end_function;
2030
2031         if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2032                 error = -ENOTTY;
2033                 goto end_function;
2034         }
2035
2036         /*prepare the output parameters in the struct */
2037         command_args.offset = command_args.physical_address - sep_dev->phys_shared_area_addr;
2038
2039         edbg("SEP Driver:physical_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
2040
2041         /* send the parameters to user application */
2042         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
2043         if (error)
2044                 goto end_function;
2045 end_function:
2046         dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2047         return error;
2048 }
2049
2050
2051 /*
2052   ?
2053 */
2054 static int sep_start_handler(void)
2055 {
2056         unsigned long reg_val;
2057         unsigned long error = 0;
2058
2059         dbg("SEP Driver:--------> sep_start_handler start\n");
2060
2061         /* wait in polling for message from SEP */
2062         do
2063                 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2064         while (!reg_val);
2065
2066         /* check the value */
2067         if (reg_val == 0x1) {
2068                 /* fatal error - read erro status from GPRO */
2069                 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2070                 goto end_function;
2071         }
2072 end_function:
2073         dbg("SEP Driver:<-------- sep_start_handler end\n");
2074         return error;
2075 }
2076
2077 /*
2078   this function handles the request for SEP initialization
2079 */
2080 static int sep_init_handler(unsigned long arg)
2081 {
2082         unsigned long message_word;
2083         unsigned long *message_ptr;
2084         struct sep_driver_init_t command_args;
2085         unsigned long counter;
2086         unsigned long error;
2087         unsigned long reg_val;
2088
2089         dbg("SEP Driver:--------> sep_init_handler start\n");
2090         error = 0;
2091
2092         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
2093
2094         dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
2095
2096         if (error)
2097                 goto end_function;
2098
2099         /* PATCH - configure the DMA to single -burst instead of multi-burst */
2100         /*sep_configure_dma_burst(); */
2101
2102         dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
2103
2104         message_ptr = (unsigned long *) command_args.message_addr;
2105
2106         /* set the base address of the SRAM  */
2107         sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
2108
2109         for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) {
2110                 get_user(message_word, message_ptr);
2111                 /* write data to SRAM */
2112                 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR, message_word);
2113                 edbg("SEP Driver:message_word is %lu\n", message_word);
2114                 /* wait for write complete */
2115                 sep_wait_sram_write(sep_dev);
2116         }
2117         dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
2118         /* signal SEP */
2119         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
2120
2121         do
2122                 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2123         while (!(reg_val & 0xFFFFFFFD));
2124
2125         dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
2126
2127         /* check the value */
2128         if (reg_val == 0x1) {
2129                 edbg("SEP Driver:init failed\n");
2130
2131                 error = sep_read_reg(sep_dev, 0x8060);
2132                 edbg("SEP Driver:sw monitor is %lu\n", error);
2133
2134                 /* fatal error - read erro status from GPRO */
2135                 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2136                 edbg("SEP Driver:error is %lu\n", error);
2137                 goto end_function;
2138         }
2139 end_function:
2140         dbg("SEP Driver:<-------- sep_init_handler end\n");
2141         return error;
2142
2143 }
2144
2145 /*
2146   this function handles the request cache and resident reallocation
2147 */
2148 static int sep_realloc_cache_resident_handler(unsigned long arg)
2149 {
2150         int error;
2151         unsigned long phys_cache_address;
2152         unsigned long phys_resident_address;
2153         struct sep_driver_realloc_cache_resident_t command_args;
2154
2155         /* copy the data */
2156         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_realloc_cache_resident_t));
2157         if (error)
2158                 goto end_function;
2159
2160         /* copy cache and resident to the their intended locations */
2161         error = sep_copy_cache_resident_to_area(command_args.cache_addr, command_args.cache_size_in_bytes, command_args.resident_addr, command_args.resident_size_in_bytes, &phys_cache_address, &phys_resident_address);
2162         if (error)
2163                 goto end_function;
2164
2165         /* lock the area (if needed) */
2166         sep_lock_cache_resident_area();
2167
2168         command_args.new_base_addr = sep_dev->phys_shared_area_addr;
2169
2170         /* find the new base address according to the lowest address between
2171            cache, resident and shared area */
2172         if (phys_resident_address < command_args.new_base_addr)
2173                 command_args.new_base_addr = phys_resident_address;
2174         if (phys_cache_address < command_args.new_base_addr)
2175                 command_args.new_base_addr = phys_cache_address;
2176
2177         /* set the return parameters */
2178         command_args.new_cache_addr = phys_cache_address;
2179         command_args.new_resident_addr = phys_resident_address;
2180
2181         /* set the new shared area */
2182         command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
2183
2184         edbg("SEP Driver:command_args.new_shared_area_addr is %08lx\n", command_args.new_shared_area_addr);
2185         edbg("SEP Driver:command_args.new_base_addr is %08lx\n", command_args.new_base_addr);
2186         edbg("SEP Driver:command_args.new_resident_addr is %08lx\n", command_args.new_resident_addr);
2187         edbg("SEP Driver:command_args.new_cache_addr is %08lx\n", command_args.new_cache_addr);
2188
2189         /* return to user */
2190         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_realloc_cache_resident_t));
2191 end_function:
2192         return error;
2193 }
2194
2195 /*
2196   this function handles the request for get time
2197 */
2198 static int sep_get_time_handler(unsigned long arg)
2199 {
2200         int error;
2201         struct sep_driver_get_time_t command_args;
2202
2203         error = sep_set_time(&command_args.time_physical_address, &command_args.time_value);
2204         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_get_time_t));
2205         return error;
2206
2207 }
2208
2209 /*
2210   This api handles the setting of API mode to blocking or non-blocking
2211 */
2212 static int sep_set_api_mode_handler(unsigned long arg)
2213 {
2214         int error;
2215         unsigned long mode_flag;
2216
2217         dbg("SEP Driver:--------> sep_set_api_mode_handler start\n");
2218
2219         error = get_user(mode_flag, &(((struct sep_driver_set_api_mode_t *) arg)->mode));
2220         if (error)
2221                 goto end_function;
2222
2223         /* set the global flag */
2224         sep_dev->block_mode_flag = mode_flag;
2225 end_function:
2226         dbg("SEP Driver:<-------- sep_set_api_mode_handler end\n");
2227         return error;
2228 }
2229
2230 /*
2231   This API handles the end transaction request
2232 */
2233 static int sep_end_transaction_handler(unsigned long arg)
2234 {
2235         dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
2236
2237 #if 0                           /*!SEP_DRIVER_POLLING_MODE */
2238         /* close IMR */
2239         sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
2240
2241         /* release IRQ line */
2242         free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
2243
2244         /* lock the sep mutex */
2245         mutex_unlock(&sep_mutex);
2246 #endif
2247
2248         dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
2249
2250         return 0;
2251 }
2252
2253 /* handler for flow done interrupt */
2254 static void sep_flow_done_handler(struct work_struct *work)
2255 {
2256         struct sep_flow_context_t *flow_data_ptr;
2257
2258         /* obtain the mutex */
2259         mutex_lock(&sep_mutex);
2260
2261         /* get the pointer to context */
2262         flow_data_ptr = (struct sep_flow_context_t *) work;
2263
2264         /* free all the current input tables in sep */
2265         sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
2266
2267         /* free all the current tables output tables in SEP (if needed) */
2268         if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
2269                 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
2270
2271         /* check if we have additional tables to be sent to SEP only input
2272            flag may be checked */
2273         if (flow_data_ptr->input_tables_flag) {
2274                 /* copy the message to the shared RAM and signal SEP */
2275                 memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes);
2276
2277                 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
2278         }
2279         mutex_unlock(&sep_mutex);
2280 }
2281
2282
2283 /*
2284   This function creates a list of tables for flow and returns the data for
2285         the first and last tables of the list
2286 */
2287 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
2288                                        unsigned long first_buff_addr, struct sep_flow_context_t *flow_data_ptr, struct sep_lli_entry_t *first_table_data_ptr, struct sep_lli_entry_t *last_table_data_ptr, bool isKernelVirtualAddress)
2289 {
2290         int error;
2291         unsigned long virt_buff_addr;
2292         unsigned long virt_buff_size;
2293         struct sep_lli_entry_t table_data;
2294         struct sep_lli_entry_t *info_entry_ptr;
2295         struct sep_lli_entry_t *prev_info_entry_ptr;
2296         unsigned long i;
2297
2298         /* init vars */
2299         error = 0;
2300         prev_info_entry_ptr = 0;
2301
2302         /* init the first table to default */
2303         table_data.physical_address = 0xffffffff;
2304         first_table_data_ptr->physical_address = 0xffffffff;
2305         table_data.block_size = 0;
2306
2307         for (i = 0; i < num_virtual_buffers; i++) {
2308                 /* get the virtual buffer address */
2309                 error = get_user(virt_buff_addr, &first_buff_addr);
2310                 if (error)
2311                         goto end_function;
2312
2313                 /* get the virtual buffer size */
2314                 first_buff_addr++;
2315                 error = get_user(virt_buff_size, &first_buff_addr);
2316                 if (error)
2317                         goto end_function;
2318
2319                 /* advance the address to point to the next pair of address|size */
2320                 first_buff_addr++;
2321
2322                 /* now prepare the one flow LLI table from the data */
2323                 error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress);
2324                 if (error)
2325                         goto end_function;
2326
2327                 if (i == 0) {
2328                         /* if this is the first table - save it to return to the user
2329                            application */
2330                         *first_table_data_ptr = table_data;
2331
2332                         /* set the pointer to info entry */
2333                         prev_info_entry_ptr = info_entry_ptr;
2334                 } else {
2335                         /* not first table - the previous table info entry should
2336                            be updated */
2337                         prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size);
2338
2339                         /* set the pointer to info entry */
2340                         prev_info_entry_ptr = info_entry_ptr;
2341                 }
2342         }
2343
2344         /* set the last table data */
2345         *last_table_data_ptr = table_data;
2346 end_function:
2347         return error;
2348 }
2349
2350
2351 /*
2352   This function creates one DMA table for flow and returns its data,
2353   and pointer to its info entry
2354 */
2355 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr, unsigned long virt_buff_size, struct sep_lli_entry_t *table_data, struct sep_lli_entry_t **info_entry_ptr, struct sep_flow_context_t *flow_data_ptr, bool isKernelVirtualAddress)
2356 {
2357         int error;
2358         /* the range in pages */
2359         unsigned long lli_array_size;
2360         struct sep_lli_entry_t *lli_array;
2361         struct sep_lli_entry_t *flow_dma_table_entry_ptr;
2362         unsigned long *start_dma_table_ptr;
2363         /* total table data counter */
2364         unsigned long dma_table_data_count;
2365         /* pointer that will keep the pointer to the pages of the virtual buffer */
2366         struct page **page_array_ptr;
2367         unsigned long entry_count;
2368
2369         /* find the space for the new table */
2370         error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
2371         if (error)
2372                 goto end_function;
2373
2374         /* check if the pages are in Kernel Virtual Address layout */
2375         if (isKernelVirtualAddress == true)
2376                 /* lock kernel buffer in the memory */
2377                 error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2378         else
2379                 /* lock user buffer in the memory */
2380                 error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2381
2382         if (error)
2383                 goto end_function;
2384
2385         /* set the pointer to page array at the beginning of table - this table is
2386            now considered taken */
2387         *start_dma_table_ptr = lli_array_size;
2388
2389         /* point to the place of the pages pointers of the table */
2390         start_dma_table_ptr++;
2391
2392         /* set the pages pointer */
2393         *start_dma_table_ptr = (unsigned long) page_array_ptr;
2394
2395         /* set the pointer to the first entry */
2396         flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr);
2397
2398         /* now create the entries for table */
2399         for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) {
2400                 flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address;
2401
2402                 flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size;
2403
2404                 /* set the total data of a table */
2405                 dma_table_data_count += lli_array[entry_count].block_size;
2406
2407                 flow_dma_table_entry_ptr++;
2408         }
2409
2410         /* set the physical address */
2411         table_data->physical_address = virt_to_phys(start_dma_table_ptr);
2412
2413         /* set the num_entries and total data size */
2414         table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count);
2415
2416         /* set the info entry */
2417         flow_dma_table_entry_ptr->physical_address = 0xffffffff;
2418         flow_dma_table_entry_ptr->block_size = 0;
2419
2420         /* set the pointer to info entry */
2421         *info_entry_ptr = flow_dma_table_entry_ptr;
2422
2423         /* the array of the lli entries */
2424         kfree(lli_array);
2425 end_function:
2426         return error;
2427 }
2428
2429
2430 /*
2431   This function returns pointer to the  flow data structure
2432   that contains the given id
2433 */
2434 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr)
2435 {
2436         unsigned long count;
2437         int error = 0;
2438
2439         /*
2440            always search for flow with id default first - in case we
2441            already started working on the flow there can be no situation
2442            when 2 flows are with default flag
2443          */
2444         for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
2445                 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
2446                         *flow_data_ptr = &sep_dev->flows_data_array[count];
2447                         break;
2448                 }
2449         }
2450
2451         if (count == SEP_DRIVER_NUM_FLOWS)
2452                 /* no flow found  */
2453                 error = -ENOMEM;
2454
2455         return error;
2456 }
2457
2458 /*
2459   this function find a space for the new flow dma table
2460 */
2461 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr)
2462 {
2463         int error = 0;
2464         /* pointer to the id field of the flow dma table */
2465         unsigned long *start_table_ptr;
2466         unsigned long flow_dma_area_start_addr;
2467         unsigned long flow_dma_area_end_addr;
2468         /* maximum table size in words */
2469         unsigned long table_size_in_words;
2470
2471         /* find the start address of the flow DMA table area */
2472         flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
2473
2474         /* set end address of the flow table area */
2475         flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
2476
2477         /* set table size in words */
2478         table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
2479
2480         /* set the pointer to the start address of DMA area */
2481         start_table_ptr = (unsigned long *) flow_dma_area_start_addr;
2482
2483         /* find the space for the next table */
2484         while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr))
2485                 start_table_ptr += table_size_in_words;
2486
2487         /* check if we reached the end of floa tables area */
2488         if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr)
2489                 error = -1;
2490         else
2491                 *table_address_ptr = start_table_ptr;
2492
2493         return error;
2494 }
2495
2496 /*
2497   this function goes over all the flow tables connected to the given
2498         table and deallocate them
2499 */
2500 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
2501 {
2502         /* id pointer */
2503         unsigned long *table_ptr;
2504         /* end address of the flow dma area */
2505         unsigned long num_entries;
2506         unsigned long num_pages;
2507         struct page **pages_ptr;
2508         /* maximum table size in words */
2509         struct sep_lli_entry_t *info_entry_ptr;
2510
2511         /* set the pointer to the first table */
2512         table_ptr = (unsigned long *) first_table_ptr->physical_address;
2513
2514         /* set the num of entries */
2515         num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
2516             & SEP_NUM_ENTRIES_MASK;
2517
2518         /* go over all the connected tables */
2519         while (*table_ptr != 0xffffffff) {
2520                 /* get number of pages */
2521                 num_pages = *(table_ptr - 2);
2522
2523                 /* get the pointer to the pages */
2524                 pages_ptr = (struct page **) (*(table_ptr - 1));
2525
2526                 /* free the pages */
2527                 sep_free_dma_pages(pages_ptr, num_pages, 1);
2528
2529                 /* goto to the info entry */
2530                 info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1);
2531
2532                 table_ptr = (unsigned long *) info_entry_ptr->physical_address;
2533                 num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2534         }
2535
2536         return;
2537 }
2538
2539 /*
2540   This function handler the set flow id command
2541 */
2542 static int sep_set_flow_id_handler(unsigned long arg)
2543 {
2544         int error;
2545         unsigned long flow_id;
2546         struct sep_flow_context_t *flow_data_ptr;
2547
2548         dbg("------------>SEP Driver: sep_set_flow_id_handler start\n");
2549
2550         error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id));
2551         if (error)
2552                 goto end_function;
2553
2554         /* find the flow data structure that was just used for creating new flow
2555            - its id should be default */
2556         error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
2557         if (error)
2558                 goto end_function;
2559
2560         /* set flow id */
2561         flow_data_ptr->flow_id = flow_id;
2562
2563 end_function:
2564         dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n");
2565         return error;
2566 }
2567
2568
2569 /*
2570   calculates time and sets it at the predefined address
2571 */
2572 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr)
2573 {
2574         struct timeval time;
2575         /* address of time in the kernel */
2576         unsigned long time_addr;
2577
2578
2579         dbg("SEP Driver:--------> sep_set_time start\n");
2580
2581         do_gettimeofday(&time);
2582
2583         /* set value in the SYSTEM MEMORY offset */
2584         time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
2585
2586         *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN;
2587         *(unsigned long *) (time_addr + 4) = time.tv_sec;
2588
2589         edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec);
2590         edbg("SEP Driver:time_addr is %lu\n", time_addr);
2591         edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr);
2592
2593         /* set the output parameters if needed */
2594         if (address_ptr)
2595                 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
2596
2597         if (time_in_sec_ptr)
2598                 *time_in_sec_ptr = time.tv_sec;
2599
2600         dbg("SEP Driver:<-------- sep_set_time end\n");
2601
2602         return 0;
2603 }
2604
2605 static void sep_wait_busy(struct sep_device *dev)
2606 {
2607         u32 reg;
2608
2609         do {
2610                 reg = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
2611         } while (reg);
2612 }
2613
2614 /*
2615   PATCH for configuring the DMA to single burst instead of multi-burst
2616 */
2617 static void sep_configure_dma_burst(void)
2618 {
2619 #define          HW_AHB_RD_WR_BURSTS_REG_ADDR            0x0E10UL
2620
2621         dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
2622
2623         /* request access to registers from SEP */
2624         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2625
2626         dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
2627
2628         sep_wait_busy(sep_dev);
2629
2630         dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
2631
2632         /* set the DMA burst register to single burst */
2633         sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
2634
2635         /* release the sep busy */
2636         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
2637         sep_wait_busy(sep_dev);
2638
2639         dbg("SEP Driver:<-------- sep_configure_dma_burst done  \n");
2640
2641 }
2642
2643 module_init(sep_init);
2644 module_exit(sep_exit);
2645
2646 MODULE_LICENSE("GPL");