]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/sep/sep_main_mod.c
Staging: sep: priceless ...
[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 end_function_with_error:
1946         /* free the allocated tables */
1947         sep_deallocated_flow_tables(&first_table_data);
1948 end_function:
1949         dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
1950         return error;
1951 }
1952
1953 /*
1954   this function add the flow add message to the specific flow
1955 */
1956 static int sep_add_flow_tables_message_handler(unsigned long arg)
1957 {
1958         int error;
1959         struct sep_driver_add_message_t command_args;
1960         struct sep_flow_context_t *flow_context_ptr;
1961
1962         dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
1963
1964         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
1965         if (error)
1966                 goto end_function;
1967
1968         /* check input */
1969         if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
1970                 error = -ENOMEM;
1971                 goto end_function;
1972         }
1973
1974         /* find the flow context */
1975         error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1976         if (error)
1977                 goto end_function;
1978
1979         /* copy the message into context */
1980         flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
1981         error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
1982 end_function:
1983         dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
1984         return error;
1985 }
1986
1987
1988 /*
1989   this function returns the physical and virtual addresses of the static pool
1990 */
1991 static int sep_get_static_pool_addr_handler(unsigned long arg)
1992 {
1993         int error;
1994         struct sep_driver_static_pool_addr_t command_args;
1995
1996         dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
1997
1998         /*prepare the output parameters in the struct */
1999         command_args.physical_static_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2000         command_args.virtual_static_address = sep_dev->shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2001
2002         edbg("SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
2003
2004         /* send the parameters to user application */
2005         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
2006         dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2007         return error;
2008 }
2009
2010 /*
2011   this address gets the offset of the physical address from the start
2012   of the mapped area
2013 */
2014 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2015 {
2016         int error;
2017         struct sep_driver_get_mapped_offset_t command_args;
2018
2019         dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2020
2021         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
2022         if (error)
2023                 goto end_function;
2024
2025         if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2026                 error = -ENOTTY;
2027                 goto end_function;
2028         }
2029
2030         /*prepare the output parameters in the struct */
2031         command_args.offset = command_args.physical_address - sep_dev->phys_shared_area_addr;
2032
2033         edbg("SEP Driver:physical_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
2034
2035         /* send the parameters to user application */
2036         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
2037 end_function:
2038         dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2039         return error;
2040 }
2041
2042
2043 /*
2044   ?
2045 */
2046 static int sep_start_handler(void)
2047 {
2048         unsigned long reg_val;
2049         unsigned long error = 0;
2050
2051         dbg("SEP Driver:--------> sep_start_handler start\n");
2052
2053         /* wait in polling for message from SEP */
2054         do
2055                 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2056         while (!reg_val);
2057
2058         /* check the value */
2059         if (reg_val == 0x1)
2060                 /* fatal error - read erro status from GPRO */
2061                 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2062 end_function:
2063         dbg("SEP Driver:<-------- sep_start_handler end\n");
2064         return error;
2065 }
2066
2067 /*
2068   this function handles the request for SEP initialization
2069 */
2070 static int sep_init_handler(unsigned long arg)
2071 {
2072         unsigned long message_word;
2073         unsigned long *message_ptr;
2074         struct sep_driver_init_t command_args;
2075         unsigned long counter;
2076         unsigned long error;
2077         unsigned long reg_val;
2078
2079         dbg("SEP Driver:--------> sep_init_handler start\n");
2080         error = 0;
2081
2082         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
2083
2084         dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
2085
2086         if (error)
2087                 goto end_function;
2088
2089         /* PATCH - configure the DMA to single -burst instead of multi-burst */
2090         /*sep_configure_dma_burst(); */
2091
2092         dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
2093
2094         message_ptr = (unsigned long *) command_args.message_addr;
2095
2096         /* set the base address of the SRAM  */
2097         sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
2098
2099         for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) {
2100                 get_user(message_word, message_ptr);
2101                 /* write data to SRAM */
2102                 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR, message_word);
2103                 edbg("SEP Driver:message_word is %lu\n", message_word);
2104                 /* wait for write complete */
2105                 sep_wait_sram_write(sep_dev);
2106         }
2107         dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
2108         /* signal SEP */
2109         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
2110
2111         do
2112                 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2113         while (!(reg_val & 0xFFFFFFFD));
2114
2115         dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
2116
2117         /* check the value */
2118         if (reg_val == 0x1) {
2119                 edbg("SEP Driver:init failed\n");
2120
2121                 error = sep_read_reg(sep_dev, 0x8060);
2122                 edbg("SEP Driver:sw monitor is %lu\n", error);
2123
2124                 /* fatal error - read erro status from GPRO */
2125                 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2126                 edbg("SEP Driver:error is %lu\n", error);
2127         }
2128 end_function:
2129         dbg("SEP Driver:<-------- sep_init_handler end\n");
2130         return error;
2131
2132 }
2133
2134 /*
2135   this function handles the request cache and resident reallocation
2136 */
2137 static int sep_realloc_cache_resident_handler(unsigned long arg)
2138 {
2139         int error;
2140         unsigned long phys_cache_address;
2141         unsigned long phys_resident_address;
2142         struct sep_driver_realloc_cache_resident_t command_args;
2143
2144         /* copy the data */
2145         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_realloc_cache_resident_t));
2146         if (error)
2147                 goto end_function;
2148
2149         /* copy cache and resident to the their intended locations */
2150         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);
2151         if (error)
2152                 goto end_function;
2153
2154         /* lock the area (if needed) */
2155         sep_lock_cache_resident_area();
2156
2157         command_args.new_base_addr = sep_dev->phys_shared_area_addr;
2158
2159         /* find the new base address according to the lowest address between
2160            cache, resident and shared area */
2161         if (phys_resident_address < command_args.new_base_addr)
2162                 command_args.new_base_addr = phys_resident_address;
2163         if (phys_cache_address < command_args.new_base_addr)
2164                 command_args.new_base_addr = phys_cache_address;
2165
2166         /* set the return parameters */
2167         command_args.new_cache_addr = phys_cache_address;
2168         command_args.new_resident_addr = phys_resident_address;
2169
2170         /* set the new shared area */
2171         command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
2172
2173         edbg("SEP Driver:command_args.new_shared_area_addr is %08lx\n", command_args.new_shared_area_addr);
2174         edbg("SEP Driver:command_args.new_base_addr is %08lx\n", command_args.new_base_addr);
2175         edbg("SEP Driver:command_args.new_resident_addr is %08lx\n", command_args.new_resident_addr);
2176         edbg("SEP Driver:command_args.new_cache_addr is %08lx\n", command_args.new_cache_addr);
2177
2178         /* return to user */
2179         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_realloc_cache_resident_t));
2180 end_function:
2181         return error;
2182 }
2183
2184 /*
2185   this function handles the request for get time
2186 */
2187 static int sep_get_time_handler(unsigned long arg)
2188 {
2189         int error;
2190         struct sep_driver_get_time_t command_args;
2191
2192         error = sep_set_time(&command_args.time_physical_address, &command_args.time_value);
2193         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_get_time_t));
2194         return error;
2195
2196 }
2197
2198 /*
2199   This api handles the setting of API mode to blocking or non-blocking
2200 */
2201 static int sep_set_api_mode_handler(unsigned long arg)
2202 {
2203         int error;
2204         unsigned long mode_flag;
2205
2206         dbg("SEP Driver:--------> sep_set_api_mode_handler start\n");
2207
2208         error = get_user(mode_flag, &(((struct sep_driver_set_api_mode_t *) arg)->mode));
2209         if (error)
2210                 goto end_function;
2211
2212         /* set the global flag */
2213         sep_dev->block_mode_flag = mode_flag;
2214 end_function:
2215         dbg("SEP Driver:<-------- sep_set_api_mode_handler end\n");
2216         return error;
2217 }
2218
2219 /*
2220   This API handles the end transaction request
2221 */
2222 static int sep_end_transaction_handler(unsigned long arg)
2223 {
2224         dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
2225
2226 #if 0                           /*!SEP_DRIVER_POLLING_MODE */
2227         /* close IMR */
2228         sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
2229
2230         /* release IRQ line */
2231         free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
2232
2233         /* lock the sep mutex */
2234         mutex_unlock(&sep_mutex);
2235 #endif
2236
2237         dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
2238
2239         return 0;
2240 }
2241
2242 /* handler for flow done interrupt */
2243 static void sep_flow_done_handler(struct work_struct *work)
2244 {
2245         struct sep_flow_context_t *flow_data_ptr;
2246
2247         /* obtain the mutex */
2248         mutex_lock(&sep_mutex);
2249
2250         /* get the pointer to context */
2251         flow_data_ptr = (struct sep_flow_context_t *) work;
2252
2253         /* free all the current input tables in sep */
2254         sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
2255
2256         /* free all the current tables output tables in SEP (if needed) */
2257         if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
2258                 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
2259
2260         /* check if we have additional tables to be sent to SEP only input
2261            flag may be checked */
2262         if (flow_data_ptr->input_tables_flag) {
2263                 /* copy the message to the shared RAM and signal SEP */
2264                 memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes);
2265
2266                 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
2267         }
2268         mutex_unlock(&sep_mutex);
2269 }
2270
2271
2272 /*
2273   This function creates a list of tables for flow and returns the data for
2274         the first and last tables of the list
2275 */
2276 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
2277                                        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)
2278 {
2279         int error;
2280         unsigned long virt_buff_addr;
2281         unsigned long virt_buff_size;
2282         struct sep_lli_entry_t table_data;
2283         struct sep_lli_entry_t *info_entry_ptr;
2284         struct sep_lli_entry_t *prev_info_entry_ptr;
2285         unsigned long i;
2286
2287         /* init vars */
2288         error = 0;
2289         prev_info_entry_ptr = 0;
2290
2291         /* init the first table to default */
2292         table_data.physical_address = 0xffffffff;
2293         first_table_data_ptr->physical_address = 0xffffffff;
2294         table_data.block_size = 0;
2295
2296         for (i = 0; i < num_virtual_buffers; i++) {
2297                 /* get the virtual buffer address */
2298                 error = get_user(virt_buff_addr, &first_buff_addr);
2299                 if (error)
2300                         goto end_function;
2301
2302                 /* get the virtual buffer size */
2303                 first_buff_addr++;
2304                 error = get_user(virt_buff_size, &first_buff_addr);
2305                 if (error)
2306                         goto end_function;
2307
2308                 /* advance the address to point to the next pair of address|size */
2309                 first_buff_addr++;
2310
2311                 /* now prepare the one flow LLI table from the data */
2312                 error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress);
2313                 if (error)
2314                         goto end_function;
2315
2316                 if (i == 0) {
2317                         /* if this is the first table - save it to return to the user
2318                            application */
2319                         *first_table_data_ptr = table_data;
2320
2321                         /* set the pointer to info entry */
2322                         prev_info_entry_ptr = info_entry_ptr;
2323                 } else {
2324                         /* not first table - the previous table info entry should
2325                            be updated */
2326                         prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size);
2327
2328                         /* set the pointer to info entry */
2329                         prev_info_entry_ptr = info_entry_ptr;
2330                 }
2331         }
2332
2333         /* set the last table data */
2334         *last_table_data_ptr = table_data;
2335 end_function:
2336         return error;
2337 }
2338
2339
2340 /*
2341   This function creates one DMA table for flow and returns its data,
2342   and pointer to its info entry
2343 */
2344 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)
2345 {
2346         int error;
2347         /* the range in pages */
2348         unsigned long lli_array_size;
2349         struct sep_lli_entry_t *lli_array;
2350         struct sep_lli_entry_t *flow_dma_table_entry_ptr;
2351         unsigned long *start_dma_table_ptr;
2352         /* total table data counter */
2353         unsigned long dma_table_data_count;
2354         /* pointer that will keep the pointer to the pages of the virtual buffer */
2355         struct page **page_array_ptr;
2356         unsigned long entry_count;
2357
2358         /* find the space for the new table */
2359         error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
2360         if (error)
2361                 goto end_function;
2362
2363         /* check if the pages are in Kernel Virtual Address layout */
2364         if (isKernelVirtualAddress == true)
2365                 /* lock kernel buffer in the memory */
2366                 error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2367         else
2368                 /* lock user buffer in the memory */
2369                 error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2370
2371         if (error)
2372                 goto end_function;
2373
2374         /* set the pointer to page array at the beginning of table - this table is
2375            now considered taken */
2376         *start_dma_table_ptr = lli_array_size;
2377
2378         /* point to the place of the pages pointers of the table */
2379         start_dma_table_ptr++;
2380
2381         /* set the pages pointer */
2382         *start_dma_table_ptr = (unsigned long) page_array_ptr;
2383
2384         /* set the pointer to the first entry */
2385         flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr);
2386
2387         /* now create the entries for table */
2388         for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) {
2389                 flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address;
2390
2391                 flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size;
2392
2393                 /* set the total data of a table */
2394                 dma_table_data_count += lli_array[entry_count].block_size;
2395
2396                 flow_dma_table_entry_ptr++;
2397         }
2398
2399         /* set the physical address */
2400         table_data->physical_address = virt_to_phys(start_dma_table_ptr);
2401
2402         /* set the num_entries and total data size */
2403         table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count);
2404
2405         /* set the info entry */
2406         flow_dma_table_entry_ptr->physical_address = 0xffffffff;
2407         flow_dma_table_entry_ptr->block_size = 0;
2408
2409         /* set the pointer to info entry */
2410         *info_entry_ptr = flow_dma_table_entry_ptr;
2411
2412         /* the array of the lli entries */
2413         kfree(lli_array);
2414 end_function:
2415         return error;
2416 }
2417
2418
2419 /*
2420   This function returns pointer to the  flow data structure
2421   that contains the given id
2422 */
2423 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr)
2424 {
2425         unsigned long count;
2426         int error = 0;
2427
2428         /*
2429            always search for flow with id default first - in case we
2430            already started working on the flow there can be no situation
2431            when 2 flows are with default flag
2432          */
2433         for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
2434                 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
2435                         *flow_data_ptr = &sep_dev->flows_data_array[count];
2436                         break;
2437                 }
2438         }
2439
2440         if (count == SEP_DRIVER_NUM_FLOWS)
2441                 /* no flow found  */
2442                 error = -ENOMEM;
2443
2444         return error;
2445 }
2446
2447 /*
2448   this function find a space for the new flow dma table
2449 */
2450 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr)
2451 {
2452         int error = 0;
2453         /* pointer to the id field of the flow dma table */
2454         unsigned long *start_table_ptr;
2455         unsigned long flow_dma_area_start_addr;
2456         unsigned long flow_dma_area_end_addr;
2457         /* maximum table size in words */
2458         unsigned long table_size_in_words;
2459
2460         /* find the start address of the flow DMA table area */
2461         flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
2462
2463         /* set end address of the flow table area */
2464         flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
2465
2466         /* set table size in words */
2467         table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
2468
2469         /* set the pointer to the start address of DMA area */
2470         start_table_ptr = (unsigned long *) flow_dma_area_start_addr;
2471
2472         /* find the space for the next table */
2473         while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr))
2474                 start_table_ptr += table_size_in_words;
2475
2476         /* check if we reached the end of floa tables area */
2477         if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr)
2478                 error = -1;
2479         else
2480                 *table_address_ptr = start_table_ptr;
2481
2482         return error;
2483 }
2484
2485 /*
2486   this function goes over all the flow tables connected to the given
2487         table and deallocate them
2488 */
2489 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
2490 {
2491         /* id pointer */
2492         unsigned long *table_ptr;
2493         /* end address of the flow dma area */
2494         unsigned long num_entries;
2495         unsigned long num_pages;
2496         struct page **pages_ptr;
2497         /* maximum table size in words */
2498         struct sep_lli_entry_t *info_entry_ptr;
2499
2500         /* set the pointer to the first table */
2501         table_ptr = (unsigned long *) first_table_ptr->physical_address;
2502
2503         /* set the num of entries */
2504         num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
2505             & SEP_NUM_ENTRIES_MASK;
2506
2507         /* go over all the connected tables */
2508         while (*table_ptr != 0xffffffff) {
2509                 /* get number of pages */
2510                 num_pages = *(table_ptr - 2);
2511
2512                 /* get the pointer to the pages */
2513                 pages_ptr = (struct page **) (*(table_ptr - 1));
2514
2515                 /* free the pages */
2516                 sep_free_dma_pages(pages_ptr, num_pages, 1);
2517
2518                 /* goto to the info entry */
2519                 info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1);
2520
2521                 table_ptr = (unsigned long *) info_entry_ptr->physical_address;
2522                 num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2523         }
2524
2525         return;
2526 }
2527
2528 /*
2529   This function handler the set flow id command
2530 */
2531 static int sep_set_flow_id_handler(unsigned long arg)
2532 {
2533         int error;
2534         unsigned long flow_id;
2535         struct sep_flow_context_t *flow_data_ptr;
2536
2537         dbg("------------>SEP Driver: sep_set_flow_id_handler start\n");
2538
2539         error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id));
2540         if (error)
2541                 goto end_function;
2542
2543         /* find the flow data structure that was just used for creating new flow
2544            - its id should be default */
2545         error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
2546         if (error)
2547                 goto end_function;
2548
2549         /* set flow id */
2550         flow_data_ptr->flow_id = flow_id;
2551
2552 end_function:
2553         dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n");
2554         return error;
2555 }
2556
2557
2558 /*
2559   calculates time and sets it at the predefined address
2560 */
2561 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr)
2562 {
2563         struct timeval time;
2564         /* address of time in the kernel */
2565         unsigned long time_addr;
2566
2567
2568         dbg("SEP Driver:--------> sep_set_time start\n");
2569
2570         do_gettimeofday(&time);
2571
2572         /* set value in the SYSTEM MEMORY offset */
2573         time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
2574
2575         *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN;
2576         *(unsigned long *) (time_addr + 4) = time.tv_sec;
2577
2578         edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec);
2579         edbg("SEP Driver:time_addr is %lu\n", time_addr);
2580         edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr);
2581
2582         /* set the output parameters if needed */
2583         if (address_ptr)
2584                 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
2585
2586         if (time_in_sec_ptr)
2587                 *time_in_sec_ptr = time.tv_sec;
2588
2589         dbg("SEP Driver:<-------- sep_set_time end\n");
2590
2591         return 0;
2592 }
2593
2594 static void sep_wait_busy(struct sep_device *dev)
2595 {
2596         u32 reg;
2597
2598         do {
2599                 reg = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
2600         } while (reg);
2601 }
2602
2603 /*
2604   PATCH for configuring the DMA to single burst instead of multi-burst
2605 */
2606 static void sep_configure_dma_burst(void)
2607 {
2608 #define          HW_AHB_RD_WR_BURSTS_REG_ADDR            0x0E10UL
2609
2610         dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
2611
2612         /* request access to registers from SEP */
2613         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2614
2615         dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
2616
2617         sep_wait_busy(sep_dev);
2618
2619         dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
2620
2621         /* set the DMA burst register to single burst */
2622         sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
2623
2624         /* release the sep busy */
2625         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
2626         sep_wait_busy(sep_dev);
2627
2628         dbg("SEP Driver:<-------- sep_configure_dma_burst done  \n");
2629
2630 }
2631
2632 module_init(sep_init);
2633 module_exit(sep_exit);
2634
2635 MODULE_LICENSE("GPL");