]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/sep/sep_main_mod.c
Staging: sep: Create a structure to hold all the current crap spewed about as globals
[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(
119                         struct sep_lli_entry_t  *lli_in_array_ptr,
120                         unsigned long   num_array_entries);
121 /*
122   this functions builds ont lli table from the lli_array according to the
123   given size of data
124 */
125 static void sep_build_lli_table(struct sep_lli_entry_t  *lli_array_ptr,
126                         struct sep_lli_entry_t          *lli_table_ptr,
127                         unsigned long           *num_processed_entries_ptr,
128                         unsigned long           *num_table_entries_ptr,
129                         unsigned long   table_data_size);
130
131 /*
132   this function goes over the list of the print created tables and prints
133   all the data
134 */
135 static void sep_debug_print_lli_tables(struct sep_lli_entry_t   *lli_table_ptr,
136                                         unsigned long   num_table_entries,
137                                         unsigned long   table_data_size);
138
139
140
141 /*
142   This function raises interrupt to SEPm that signals that is has a new
143   command from HOST
144 */
145 static void sep_send_command_handler(void);
146
147
148 /*
149   This function raises interrupt to SEP that signals that is has a
150   new reply from HOST
151 */
152 static void sep_send_reply_command_handler(void);
153
154 /*
155   This function handles the allocate data pool memory request
156   This function returns calculates the physical address of the allocated memory
157   and the offset of this area from the mapped address. Therefore, the FVOs in
158   user space can calculate the exact virtual address of this allocated memory
159 */
160 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
161
162
163 /*
164   This function  handles write into allocated data pool command
165 */
166 static int sep_write_into_data_pool_handler(unsigned long arg);
167
168 /*
169   this function handles the read from data pool command
170 */
171 static int sep_read_from_data_pool_handler(unsigned long arg);
172
173 /*
174   this function handles tha request for creation of the DMA table
175   for the synchronic symmetric operations (AES,DES)
176 */
177 static int sep_create_sync_dma_tables_handler(unsigned long arg);
178
179 /*
180   this function handles the request to create the DMA tables for flow
181 */
182 static int sep_create_flow_dma_tables_handler(unsigned long arg);
183
184 /*
185   This API handles the end transaction request
186 */
187 static int sep_end_transaction_handler(unsigned long arg);
188
189
190 /*
191   this function handles add tables to flow
192 */
193 static int sep_add_flow_tables_handler(unsigned long arg);
194
195 /*
196   this function add the flow add message to the specific flow
197 */
198 static int sep_add_flow_tables_message_handler(unsigned long arg);
199
200 /*
201   this function handles the request for SEP start
202 */
203 static int sep_start_handler(void);
204
205 /*
206   this function handles the request for SEP initialization
207 */
208 static int sep_init_handler(unsigned long arg);
209
210 /*
211   this function handles the request cache and resident reallocation
212 */
213 static int sep_realloc_cache_resident_handler(unsigned long arg);
214
215
216 /*
217   This api handles the setting of API mode to blocking or non-blocking
218 */
219 static int sep_set_api_mode_handler(unsigned long arg);
220
221 /* handler for flow done interrupt */
222 static void sep_flow_done_handler(struct work_struct            *work);
223
224 /*
225   This function locks all the physical pages of the kernel virtual buffer
226   and construct a basic lli  array, where each entry holds the physical
227   page address and the size that application data holds in this physical pages
228 */
229 static int sep_lock_kernel_pages(unsigned long  kernel_virt_addr,
230                                 unsigned long   data_size,
231                                 unsigned long   *num_pages_ptr,
232                                 struct sep_lli_entry_t  **lli_array_ptr,
233                                 struct page     ***page_array_ptr);
234
235 /*
236   This function creates one DMA table for flow and returns its data,
237   and pointer to its info entry
238 */
239 static int sep_prepare_one_flow_dma_table(unsigned long  virt_buff_addr,
240                         unsigned long    virt_buff_size,
241                         struct sep_lli_entry_t          *table_data,
242                         struct sep_lli_entry_t          **info_entry_ptr,
243                         struct sep_flow_context_t       *flow_data_ptr,
244                         bool                    isKernelVirtualAddress);
245
246 /*
247   This function creates a list of tables for flow and returns the data for the
248   first and last tables of the list
249 */
250 static int sep_prepare_flow_dma_tables(unsigned long    num_virtual_buffers,
251                 unsigned long           first_buff_addr,
252                 struct sep_flow_context_t       *flow_data_ptr,
253                 struct sep_lli_entry_t          *first_table_data_ptr,
254                 struct sep_lli_entry_t          *last_table_data_ptr,
255                 bool                    isKernelVirtualAddress);
256
257 /*
258   this function find a space for the new flow dma table
259 */
260 static int sep_find_free_flow_dma_table_space(
261         unsigned long           **table_address_ptr);
262
263 /*
264   this function goes over all the flow tables connected to the given table and
265   deallocate them
266 */
267 static void sep_deallocated_flow_tables(
268                 struct sep_lli_entry_t *first_table_ptr);
269
270 /*
271   This function handler the set flow id command
272 */
273 static int sep_set_flow_id_handler(unsigned long arg);
274
275 /*
276   This function returns pointer to the  flow data structure
277   that conatins the given id
278 */
279 static int sep_find_flow_context(unsigned long flow_id,
280                                 struct sep_flow_context_t **flow_data_ptr);
281
282
283 /*
284   this function returns the physical and virtual addresses of the static pool
285 */
286 static int sep_get_static_pool_addr_handler(unsigned long arg);
287
288 /*
289   this address gets the offset of the physical address from the start of
290   the mapped area
291 */
292 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
293
294
295 /*
296   this function handles the request for get time
297 */
298 static int sep_get_time_handler(unsigned long arg);
299
300 /*
301   calculates time and sets it at the predefined address
302 */
303 static int sep_set_time(unsigned long   *address_ptr,
304                         unsigned long   *time_in_sec_ptr);
305
306 /*
307   PATCH for configuring the DMA to single burst instead of multi-burst
308 */
309 static void sep_configure_dma_burst(void);
310
311 /*
312         This function locks all the physical pages of the
313         application virtual buffer and construct a basic lli
314         array, where each entry holds the physical page address
315         and the size that application data holds in this physical pages
316 */
317 static int sep_lock_user_pages(unsigned long  app_virt_addr,
318                                 unsigned long       data_size,
319                                 unsigned long      *num_pages_ptr,
320                                 struct sep_lli_entry_t   **lli_array_ptr,
321                                 struct page      ***page_array_ptr);
322
323 /*---------------------------------------------
324         FUNCTIONS
325 -----------------------------------------------*/
326
327 /*
328   this function locks SEP by locking the semaphore
329 */
330 int sep_lock()
331 {
332   mutex_lock(&sep_mutex);
333
334   return 0;
335 }
336
337 /*
338   this function unlocks SEP
339 */
340 void sep_unlock()
341 {
342   /* release mutex */
343   mutex_unlock(&sep_mutex);
344 }
345
346 /*
347   this function returns the address of the message shared area
348 */
349 void sep_map_shared_area(unsigned long          *mappedAddr_ptr)
350 {
351   *mappedAddr_ptr = sep_dev->shared_area_addr;
352 }
353
354 /*
355   this function returns the address of the message shared area
356 */
357 void sep_send_msg_rdy_cmd()
358 {
359   sep_send_command_handler();
360 }
361
362 /* this functions frees all the resources that were allocated for the building
363 of the LLI DMA tables */
364 void sep_free_dma_resources()
365 {
366   sep_free_dma_table_data_handler();
367 }
368
369 /* poll(suspend), until reply from sep */
370 void sep_driver_poll()
371 {
372   unsigned long retVal = 0;
373
374 #ifdef SEP_DRIVER_POLLING_MODE
375
376   while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
377         SEP_READ_REGISTER(sep_dev->reg_base_address +
378                         HW_HOST_SEP_HOST_GPR2_REG_ADDR,
379                         retVal);
380
381   sep_dev->sep_to_host_reply_counter++;
382 #else
383   /* poll, until reply from sep */
384   wait_event(g_sep_event,
385   (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
386
387 #endif
388 }
389
390 /*----------------------------------------------------------------------
391   open function of the character driver - must only lock the mutex
392         must also release the memory data pool allocations
393 ------------------------------------------------------------------------*/
394 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
395 {
396   /* return value */
397   int                   error;
398
399   /*-----------------
400         CODE
401   ---------------------*/
402
403   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> open start\n");
404
405   error = 0;
406
407   /* check the blocking mode */
408   if (sep_dev->block_mode_flag)
409         /* lock mutex */
410         mutex_lock(&sep_mutex);
411   else
412         error = mutex_trylock(&sep_mutex);
413
414   /* check the error */
415   if (error) {
416         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
417                 "SEP Driver: down_interruptible failed\n");
418
419         goto end_function;
420   }
421
422   /* release data pool allocations */
423   sep_dev->data_pool_bytes_allocated = 0;
424
425 end_function:
426
427   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- open end\n");
428
429   return error;
430 }
431
432
433
434
435 /*------------------------------------------------------------
436         release function
437 -------------------------------------------------------------*/
438 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
439 {
440   /*-----------------
441         CODE
442   ---------------------*/
443
444   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
445                 "----------->SEP Driver: sep_release start\n");
446
447 #if 0/*!SEP_DRIVER_POLLING_MODE*/
448   /* close IMR */
449   SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
450
451   /* release IRQ line */
452   free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
453
454 #endif
455
456   /* unlock the sep mutex */
457   mutex_unlock(&sep_mutex);
458
459   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
460                 "SEP Driver:<-------- sep_release end\n");
461
462   return 0;
463 }
464
465
466
467
468 /*---------------------------------------------------------------
469   map function - this functions maps the message shared area
470 -----------------------------------------------------------------*/
471 static int sep_mmap(struct file  *filp, struct vm_area_struct  *vma)
472 {
473   /* physical addr */
474   unsigned long phys_addr;
475
476   /*-----------------------
477         CODE
478   -------------------------*/
479
480   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "-------->SEP Driver: mmap start\n");
481
482   /* check that the size of the mapped range is as the size of the message
483   shared area */
484   if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
485         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
486                 "SEP Driver mmap requested size is more than allowed\n");
487         printk(KERN_WARNING "SEP Driver mmap requested size is more \
488                         than allowed\n");
489         printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
490         vma->vm_end);
491         printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
492         vma->vm_start);
493         return -EAGAIN;
494   }
495
496   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
497   "SEP Driver:g_message_shared_area_addr is %08lx\n",
498   sep_dev->message_shared_area_addr);
499
500   /* get physical address */
501   phys_addr  = sep_dev->phys_shared_area_addr;
502
503   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: phys_addr is %08lx\n",
504 phys_addr);
505
506   if (remap_pfn_range(vma,
507          vma->vm_start,
508          phys_addr >> PAGE_SHIFT,
509          vma->vm_end - vma->vm_start,
510          vma->vm_page_prot)) {
511         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
512                 "SEP Driver remap_page_range failed\n");
513         printk(KERN_WARNING  "SEP Driver remap_page_range failed\n");
514         return -EAGAIN;
515   }
516
517   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- mmap end\n");
518
519   return 0;
520 }
521
522
523 /*-----------------------------------------------
524   poll function
525 *----------------------------------------------*/
526 static unsigned int sep_poll(struct file  *filp, poll_table  *wait)
527 {
528   unsigned long count;
529
530   unsigned int  mask = 0;
531
532   /* flow id */
533   unsigned long retVal = 0;
534
535   /*----------------------------------------------
536         CODE
537   -------------------------------------------------*/
538
539   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "---------->SEP Driver poll: start\n");
540
541
542 #if SEP_DRIVER_POLLING_MODE
543
544   while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
545         SEP_READ_REGISTER(sep_dev->reg_base_address +
546         HW_HOST_SEP_HOST_GPR2_REG_ADDR,
547         retVal);
548
549         for (count = 0; count < 10 * 4; count += 4)
550         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
551         "Poll Debug Word %lu of the message is %lu\n",
552         count,
553         *((unsigned long *)(sep_dev->shared_area_addr +
554         SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
555   }
556
557   sep_dev->sep_to_host_reply_counter++;
558 #else
559   /* add the event to the polling wait table */
560   poll_wait(filp, &g_sep_event, wait);
561
562 #endif
563
564   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
565         "sep_dev->host_to_sep_send_counter is %lu\n",
566                 sep_dev->host_to_sep_send_counter);
567   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
568         "sep_dev->sep_to_host_reply_counter is %lu\n",
569         sep_dev->sep_to_host_reply_counter);
570
571   /* check if the data is ready */
572   if (sep_dev->host_to_sep_send_counter ==  sep_dev->sep_to_host_reply_counter) {
573         for (count = 0; count < 12 * 4; count += 4)
574         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
575         "Sep Mesg Word %lu of the message is %lu\n",
576         count, *((unsigned long *)(sep_dev->shared_area_addr + count)));
577
578         for (count = 0; count < 10 * 4; count += 4)
579         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
580         "Debug Data Word %lu of the message is %lu\n",
581         count,
582         *((unsigned long *)(sep_dev->shared_area_addr + 0x1800 + count)));
583
584         SEP_READ_REGISTER(sep_dev->reg_base_address +
585                 HW_HOST_SEP_HOST_GPR2_REG_ADDR,
586                 retVal);
587         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "retVal is %lu\n", retVal);
588         /* check if the this is sep reply or request */
589         if (retVal >> 31) {
590         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
591         "SEP Driver: sep request in\n");
592           /* request */
593           mask |= POLLOUT | POLLWRNORM;
594         } else {
595         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: sep reply in\n");
596           mask |= POLLIN | POLLRDNORM;
597         }
598   }
599
600   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- poll exit\n");
601   return mask;
602 }
603
604
605 static int sep_ioctl(struct inode               *inode,
606                                         struct file             *filp,
607                                         unsigned int            cmd,
608                                         unsigned long           arg)
609 {
610
611   /* error */
612   int                   error;
613
614   /*------------------------
615         CODE
616   ------------------------*/
617   error = 0;
618
619   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
620                 "------------>SEP Driver: ioctl start\n");
621
622   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: cmd is %x\n", cmd);
623
624   /* check that the command is for sep device */
625   if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
626         error = -ENOTTY;
627
628         switch (cmd) {
629         case SEP_IOCSENDSEPCOMMAND:
630
631           /* send command to SEP */
632         sep_send_command_handler();
633
634         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
635                 "SEP Driver: after sep_send_command_handler\n");
636
637           break;
638
639         case SEP_IOCSENDSEPRPLYCOMMAND:
640
641           /* send reply command to SEP */
642         sep_send_reply_command_handler();
643
644           break;
645
646         case SEP_IOCALLOCDATAPOLL:
647
648           /* allocate data pool */
649         error = sep_allocate_data_pool_memory_handler(arg);
650
651           break;
652
653         case SEP_IOCWRITEDATAPOLL:
654
655           /* write data into memory pool */
656         error = sep_write_into_data_pool_handler(arg);
657
658           break;
659
660         case SEP_IOCREADDATAPOLL:
661
662           /* read data from data pool into application memory */
663         error = sep_read_from_data_pool_handler(arg);
664
665           break;
666
667         case SEP_IOCCREATESYMDMATABLE:
668
669           /* create dma table for synhronic operation */
670         error = sep_create_sync_dma_tables_handler(arg);
671
672           break;
673
674         case SEP_IOCCREATEFLOWDMATABLE:
675
676           /* create flow dma tables */
677         error = sep_create_flow_dma_tables_handler(arg);
678
679           break;
680
681         case SEP_IOCFREEDMATABLEDATA:
682
683           /* free the pages */
684         error = sep_free_dma_table_data_handler();
685
686           break;
687
688         case SEP_IOCSETFLOWID:
689
690           /* set flow id */
691         error = sep_set_flow_id_handler(arg);
692
693           break;
694
695         case SEP_IOCADDFLOWTABLE:
696
697           /* add tables to the dynamic flow */
698         error = sep_add_flow_tables_handler(arg);
699
700           break;
701
702         case SEP_IOCADDFLOWMESSAGE:
703
704           /* add message of add tables to flow */
705         error = sep_add_flow_tables_message_handler(arg);
706
707           break;
708
709         case SEP_IOCSEPSTART:
710
711           /* start command to sep */
712         error = sep_start_handler();
713           break;
714
715         case SEP_IOCSEPINIT:
716
717           /* init command to sep */
718         error = sep_init_handler(arg);
719           break;
720
721         case SEP_IOCSETAPIMODE:
722
723           /* set non- blocking mode */
724         error = sep_set_api_mode_handler(arg);
725
726           break;
727
728         case SEP_IOCGETSTATICPOOLADDR:
729
730                 /* get the physical and virtual addresses of the static pool */
731                 error = sep_get_static_pool_addr_handler(arg);
732
733                 break;
734
735         case SEP_IOCENDTRANSACTION:
736
737         error = sep_end_transaction_handler(arg);
738
739                 break;
740
741         case SEP_IOCREALLOCCACHERES:
742
743         error = sep_realloc_cache_resident_handler(arg);
744
745           break;
746
747         case SEP_IOCGETMAPPEDADDROFFSET:
748
749         error = sep_get_physical_mapped_offset_handler(arg);
750
751           break;
752         case SEP_IOCGETIME:
753
754         error = sep_get_time_handler(arg);
755
756           break;
757
758         default:
759         error = -ENOTTY;
760           break;
761   }
762
763   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
764                 "SEP Driver:<-------- ioctl end\n");
765
766   return error;
767 }
768
769
770 /*
771   this function registers the driver to the file system
772 */
773 static int  sep_register_driver_to_fs(void)
774 {
775   /* return value */
776   int                   ret_val;
777
778   /*---------------------
779         CODE
780   -----------------------*/
781
782   ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
783   if (ret_val) {
784         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
785         "sep_driver:major number allocation failed, retval is %d\n", ret_val);
786         goto end_function;
787   }
788
789   /* set the files operations structure */
790   g_sep_fops.owner = THIS_MODULE;
791   g_sep_fops.ioctl = sep_ioctl;
792   g_sep_fops.poll = sep_poll;
793   g_sep_fops.open = sep_open;
794   g_sep_fops.release = sep_release;
795   g_sep_fops.mmap = sep_mmap;
796
797   /* init cdev */
798   cdev_init(&g_sep_cdev, &g_sep_fops);
799   g_sep_cdev.owner = THIS_MODULE;
800
801   /* register the driver with the kernel */
802   ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
803
804   if (ret_val) {
805         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
806         "sep_driver:cdev_add failed, retval is %d\n",
807         ret_val);
808         goto end_function_unregister_devnum;
809   }
810
811   goto end_function;
812
813 end_function_unregister_devnum:
814
815   /* unregister dev numbers */
816   unregister_chrdev_region(g_sep_device_number, 1);
817
818 end_function:
819
820   return ret_val;
821 }
822
823 /*
824   this function unregisters driver from fs
825 */
826 static void sep_unregister_driver_from_fs(void)
827 {
828   /*-------------------
829         CODE
830   ---------------------*/
831
832   cdev_del(&g_sep_cdev);
833
834   /* unregister dev numbers */
835   unregister_chrdev_region(g_sep_device_number, 1);
836 }
837
838 /*--------------------------------------------------------------
839   init function
840 ----------------------------------------------------------------*/
841 static int __init sep_init(void)
842 {
843   /* return value */
844   int                   ret_val;
845
846   /* counter */
847   int                   counter;
848
849   /* size to of memory for allocation */
850   int                   size;
851
852   /*------------------------
853         CODE
854   ------------------------*/
855
856   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
857                 "SEP Driver:-------->Init start\n");
858   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
859         "g_sep_shared_area_addr = %lx\n",
860         (unsigned long)&sep_dev->shared_area_addr);
861
862   ret_val = 0;
863
864 /* transaction counter that coordinates the transactions between SEP
865         and HOST */
866   sep_dev->host_to_sep_send_counter = 0;
867
868 /* counter for the messages from sep */
869   sep_dev->sep_to_host_reply_counter = 0;
870
871 /* counter for the number of bytes allocated in the pool
872 for the current transaction */
873   sep_dev->data_pool_bytes_allocated = 0;
874
875   /* set the starting mode to blocking */
876   sep_dev->block_mode_flag = 1;
877
878
879   ret_val = sep_register_driver_to_device();
880   if (ret_val) {
881         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
882         "sep_driver:sep_driver_to_device failed, ret_val is %d\n",
883         ret_val);
884         goto end_function_unregister_from_fs;
885   }
886
887   /* calculate the total size for allocation */
888   size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
889                 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
890                 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
891                 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
892                 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
893                 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
894
895
896
897   /* allocate the shared area */
898   if (sep_map_and_alloc_shared_area(size,
899                                 &sep_dev->shared_area_addr,
900                                 &sep_dev->phys_shared_area_addr)) {
901         ret_val = -ENOMEM;
902         /* allocation failed */
903         goto end_function_unmap_io_memory;
904   }
905
906   /* now set the memory regions */
907   sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
908
909   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
910         "SEP Driver: g_message_shared_area_addr is %08lx\n",
911         sep_dev->message_shared_area_addr);
912
913 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
914
915   /* send the new SHARED MESSAGE AREA to the SEP */
916   SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_HOST_SEP_GPR1_REG_ADDR,
917                         sep_dev->phys_shared_area_addr);
918
919   /* poll for SEP response */
920   SEP_READ_REGISTER(sep_dev->reg_base_address + HW_HOST_SEP_HOST_GPR1_REG_ADDR,
921                         retVal);
922   while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
923         SEP_READ_REGISTER(sep_dev->reg_base_address +
924                         HW_HOST_SEP_HOST_GPR1_REG_ADDR,
925                         retVal);
926
927   /* check the return value (register) */
928   if (retVal != sep_dev->phys_shared_area_addr) {
929         ret_val = -ENOMEM;
930         goto end_function_deallocate_message_area;
931   }
932
933 #endif
934
935   /* init the flow contextes */
936   for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
937         sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
938
939   sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
940   if (sep_dev->flow_wq_ptr == 0) {
941         ret_val = -ENOMEM;
942         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
943                 "sep_driver:flow queue creation failed\n");
944         goto end_function_deallocate_sep_shared_area;
945   }
946
947   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
948                 "SEP Driver: create flow workqueue \n");
949
950   /* register driver to fs */
951   ret_val = sep_register_driver_to_fs();
952   if (ret_val)
953         goto end_function_deallocate_sep_shared_area;
954
955   /* load the rom code */
956   sep_load_rom_code();
957
958   goto end_function;
959
960 end_function_unregister_from_fs:
961
962   /* unregister from fs */
963   sep_unregister_driver_from_fs();
964
965 end_function_deallocate_sep_shared_area:
966
967   /* de-allocate shared area */
968   sep_unmap_and_free_shared_area(size,
969                                 sep_dev->shared_area_addr,
970                                 sep_dev->phys_shared_area_addr);
971
972 end_function_unmap_io_memory:
973
974   iounmap((void *)sep_dev->reg_base_address);
975
976   /* release io memory region */
977   release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
978
979 end_function:
980
981   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,  "SEP Driver:<-------- Init end\n");
982
983   return ret_val;
984 }
985
986
987
988
989 /*-------------------------------------------------------------
990   exit function
991 --------------------------------------------------------------*/
992 static void __exit sep_exit(void)
993 {
994   /* size */
995   int                   size;
996
997   /*-----------------------------
998         CODE
999   --------------------------------*/
1000
1001   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> Exit start\n");
1002
1003   /* unregister from fs */
1004   sep_unregister_driver_from_fs();
1005
1006   /* calculate the total size for de-allocation */
1007   size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
1008                 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
1009                 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
1010                 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
1011                 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
1012                 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
1013
1014
1015   /* free shared area  */
1016   sep_unmap_and_free_shared_area(size,
1017                                 sep_dev->shared_area_addr,
1018                                 sep_dev->phys_shared_area_addr);
1019
1020   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1021                 "SEP Driver: free pages SEP SHARED AREA \n");
1022
1023   iounmap((void *)sep_dev->reg_base_address);
1024
1025   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: iounmap \n");
1026
1027   /* release io memory region */
1028   release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1029
1030   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: release_mem_region \n");
1031
1032   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,  "SEP Driver:<-------- Exit end\n");
1033 }
1034
1035
1036 /*
1037   interrupt handler function
1038 */
1039 irqreturn_t sep_inthandler(int irq, void *dev_id)
1040 {
1041   /* int error */
1042   irqreturn_t                   int_error;
1043
1044   /* error */
1045   unsigned long         error;
1046
1047   /* reg value */
1048   unsigned long         reg_val;
1049
1050   /* flow id */
1051   unsigned long          flow_id;
1052
1053   /* flow context */
1054   struct sep_flow_context_t             *flow_context_ptr;
1055
1056   /*-----------------------------
1057         CODE
1058   -----------------------------*/
1059
1060   int_error = IRQ_HANDLED;
1061
1062   /* read the IRR register to check if this is SEP interrupt */
1063   SEP_READ_REGISTER(sep_dev->reg_base_address + HW_HOST_IRR_REG_ADDR, reg_val);
1064   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Interrupt - reg is %08lx\n",
1065                         reg_val);
1066
1067   /* check if this is the flow interrupt */
1068   if (0/*reg_val & (0x1 << 11)*/) {
1069         /* read GPRO to find out the which flow is done */
1070         SEP_READ_REGISTER(sep_dev->reg_base_address + HW_HOST_IRR_REG_ADDR,
1071         flow_id);
1072
1073         /* find the contex of the flow */
1074         error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
1075         if (error)
1076                 goto end_function_with_error;
1077
1078         INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
1079
1080         /* queue the work */
1081         queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
1082
1083   } else {
1084         /* check if this is reply interrupt from SEP */
1085         if (reg_val & (0x1 << 13)) {
1086                 /* update the counter of reply messages */
1087                 sep_dev->sep_to_host_reply_counter++;
1088
1089                 /* wake up the waiting process */
1090                 wake_up(&g_sep_event);
1091         } else {
1092                 int_error = IRQ_NONE;
1093                 goto end_function;
1094         }
1095   }
1096
1097 end_function_with_error:
1098
1099   /* clear the interrupt */
1100   SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_ICR_REG_ADDR, reg_val);
1101
1102 end_function:
1103
1104   return int_error;
1105 }
1106
1107
1108 /*
1109   This function prepares only input DMA table for synhronic symmetric
1110   operations (HASH)
1111 */
1112 int sep_prepare_input_dma_table(unsigned long   app_virt_addr,
1113                                 unsigned long   data_size,
1114                                 unsigned long   block_size,
1115                                 unsigned long   *lli_table_ptr,
1116                                 unsigned long   *num_entries_ptr,
1117                                 unsigned long   *table_data_size_ptr,
1118                                 bool                    isKernelVirtualAddress)
1119
1120 {
1121   /* pointer to the info entry of the table - the last entry */
1122   struct sep_lli_entry_t                *info_entry_ptr;
1123
1124   /* array of pointers ot page */
1125   struct sep_lli_entry_t                *lli_array_ptr;
1126
1127   /* points to the first entry to be processed in the lli_in_array */
1128   unsigned long         current_entry;
1129
1130   /* num entries in the virtual buffer */
1131   unsigned long         sep_lli_entries;
1132
1133   /* lli table pointer */
1134   struct sep_lli_entry_t                *in_lli_table_ptr;
1135
1136   /* the total data in one table */
1137   unsigned long         table_data_size;
1138
1139   /* number of entries in lli table */
1140   unsigned long         num_entries_in_table;
1141
1142   /* next table address */
1143   unsigned long         lli_table_alloc_addr;
1144
1145   /* result */
1146   unsigned long         result;
1147
1148   /*------------------------
1149         CODE
1150   --------------------------*/
1151
1152   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1153                 "SEP Driver:--------> sep_prepare_input_dma_table start\n");
1154
1155   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:data_size is %lu\n",
1156                 data_size);
1157   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:block_size is %lu\n",
1158                 block_size);
1159
1160   /* initialize the pages pointers */
1161   sep_dev->in_page_array = 0;
1162   sep_dev->in_num_pages = 0;
1163
1164   if (data_size == 0) {
1165         /* special case  - created 2 entries table with zero data */
1166         in_lli_table_ptr = (struct sep_lli_entry_t *)(sep_dev->shared_area_addr +
1167                         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1168         in_lli_table_ptr->physical_address = sep_dev->shared_area_addr +
1169                         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1170         in_lli_table_ptr->block_size = 0;
1171
1172         in_lli_table_ptr++;
1173         in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1174         in_lli_table_ptr->block_size = 0;
1175
1176         *lli_table_ptr = sep_dev->phys_shared_area_addr +
1177                         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1178         *num_entries_ptr = 2;
1179         *table_data_size_ptr = 0;
1180
1181         goto end_function;
1182   }
1183
1184   /* check if the pages are in Kernel Virtual Address layout */
1185   if (isKernelVirtualAddress == true)
1186         /* lock the pages of the kernel buffer and translate them to pages */
1187         result = sep_lock_kernel_pages(app_virt_addr,
1188                                         data_size,
1189                                         &sep_dev->in_num_pages,
1190                                         &lli_array_ptr,
1191                                         &sep_dev->in_page_array);
1192   else
1193         /* lock the pages of the user buffer and translate them to pages */
1194         result = sep_lock_user_pages(app_virt_addr,
1195                                 data_size,
1196                                 &sep_dev->in_num_pages,
1197                                 &lli_array_ptr,
1198                                 &sep_dev->in_page_array);
1199
1200   if (result)
1201         return result;
1202
1203   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1204   "SEP Driver:output sep_dev->in_num_pages is %lu\n",
1205   sep_dev->in_num_pages);
1206
1207   current_entry = 0;
1208   info_entry_ptr = 0;
1209   sep_lli_entries = sep_dev->in_num_pages;
1210
1211   /* initiate to point after the message area */
1212   lli_table_alloc_addr = sep_dev->shared_area_addr +
1213                 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1214
1215   /* loop till all the entries in in array are not processed */
1216   while (current_entry < sep_lli_entries) {
1217         /* set the new input and output tables */
1218         in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1219
1220         lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1221                                 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1222
1223         /* calculate the maximum size of data for input table */
1224         table_data_size = sep_calculate_lli_table_max_size(
1225                 &lli_array_ptr[current_entry],
1226                 (sep_lli_entries - current_entry));
1227
1228         /* now calculate the table size so that it will be module block size */
1229         table_data_size = (table_data_size / block_size) * block_size;
1230
1231         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1232         "SEP Driver:output table_data_size is %lu\n",
1233         table_data_size);
1234
1235         /* construct input lli table */
1236         sep_build_lli_table(&lli_array_ptr[current_entry],
1237                                                 in_lli_table_ptr,
1238                                                 &current_entry,
1239                                                 &num_entries_in_table,
1240                                                 table_data_size);
1241
1242         if (info_entry_ptr == 0) {
1243           /* set the output parameters to physical addresses */
1244           *lli_table_ptr = sep_shared_area_virt_to_phys(
1245                   (unsigned long)in_lli_table_ptr);
1246           *num_entries_ptr = num_entries_in_table;
1247           *table_data_size_ptr = table_data_size;
1248
1249         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1250         "SEP Driver:output lli_table_in_ptr is %08lx\n",
1251         *lli_table_ptr);
1252         } else {
1253           /* update the info entry of the previous in table */
1254         info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
1255                                 (unsigned long)in_lli_table_ptr);
1256         info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
1257                                 (table_data_size);
1258         }
1259
1260         /* save the pointer to the info entry of the current tables */
1261         info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1262   }
1263
1264   /* print input tables */
1265   sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1266                         sep_shared_area_phys_to_virt(*lli_table_ptr),
1267                         *num_entries_ptr,
1268                         *table_data_size_ptr);
1269
1270   /* the array of the pages */
1271   kfree(lli_array_ptr);
1272
1273 end_function:
1274
1275   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1276                 "SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1277
1278   return 0;
1279
1280 }
1281
1282 /*
1283   This function builds input and output DMA tables for synhronic
1284   symmetric operations (AES, DES). It also checks that each table
1285   is of the modular block size
1286 */
1287 int sep_prepare_input_output_dma_table(unsigned long    app_virt_in_addr,
1288                                         unsigned long   app_virt_out_addr,
1289                                         unsigned long   data_size,
1290                                         unsigned long   block_size,
1291                                         unsigned long   *lli_table_in_ptr,
1292                                         unsigned long   *lli_table_out_ptr,
1293                                         unsigned long   *in_num_entries_ptr,
1294                                         unsigned long   *out_num_entries_ptr,
1295                                         unsigned long   *table_data_size_ptr,
1296                                         bool            isKernelVirtualAddress)
1297
1298 {
1299   /* array of pointers of page */
1300   struct sep_lli_entry_t                *lli_in_array;
1301
1302   /* array of pointers of page */
1303   struct sep_lli_entry_t                *lli_out_array;
1304
1305   /* result */
1306   int                           result;
1307
1308
1309   /*------------------------
1310         CODE
1311   --------------------------*/
1312
1313   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1314         "SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1315
1316   result = 0;
1317
1318   /* initialize the pages pointers */
1319   sep_dev->in_page_array = 0;
1320   sep_dev->out_page_array = 0;
1321
1322   /* check if the pages are in Kernel Virtual Address layout */
1323   if (isKernelVirtualAddress == true) {
1324         /* lock the pages of the kernel buffer and translate them to pages */
1325         result = sep_lock_kernel_pages(app_virt_in_addr,
1326                                 data_size,
1327                                 &sep_dev->in_num_pages,
1328                                 &lli_in_array,
1329                                 &sep_dev->in_page_array);
1330         if (result) {
1331         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1332         "SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1333         goto end_function;
1334         }
1335   } else {
1336         /* lock the pages of the user buffer and translate them to pages */
1337         result = sep_lock_user_pages(app_virt_in_addr,
1338                                         data_size,
1339                                         &sep_dev->in_num_pages,
1340                                         &lli_in_array,
1341                                         &sep_dev->in_page_array);
1342         if (result) {
1343         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1344         "SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1345         goto end_function;
1346         }
1347   }
1348
1349   if (isKernelVirtualAddress == true) {
1350         result = sep_lock_kernel_pages(app_virt_out_addr,
1351                                 data_size,
1352                                 &sep_dev->out_num_pages,
1353                                 &lli_out_array,
1354                                 &sep_dev->out_page_array);
1355         if (result) {
1356         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1357         "SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1358         goto end_function_with_error1;
1359         }
1360   } else {
1361         result = sep_lock_user_pages(app_virt_out_addr,
1362                                         data_size,
1363                                         &sep_dev->out_num_pages,
1364                                         &lli_out_array,
1365                                         &sep_dev->out_page_array);
1366         if (result) {
1367         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1368         "SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1369         goto end_function_with_error1;
1370         }
1371   }
1372
1373
1374   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1375         "sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1376         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1377         "sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1378         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1379         "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
1380         SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1381
1382
1383   /* call the fucntion that creates table from the lli arrays */
1384   result = sep_construct_dma_tables_from_lli(lli_in_array,
1385                                         sep_dev->in_num_pages,
1386                                         lli_out_array,
1387                                         sep_dev->out_num_pages,
1388                                          block_size,
1389                                         lli_table_in_ptr,
1390                                         lli_table_out_ptr,
1391                                         in_num_entries_ptr,
1392                                         out_num_entries_ptr,
1393                                         table_data_size_ptr);
1394   if (result) {
1395         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1396                 "SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1397         goto end_function_with_error2;
1398   }
1399
1400   /* fall through - free the lli entry arrays */
1401
1402   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "in_num_entries_ptr is %08lx\n",
1403         *in_num_entries_ptr);
1404   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "out_num_entries_ptr is %08lx\n",
1405         *out_num_entries_ptr);
1406   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "table_data_size_ptr is %08lx\n",
1407         *table_data_size_ptr);
1408
1409
1410 end_function_with_error2:
1411
1412   kfree(lli_out_array);
1413
1414 end_function_with_error1:
1415
1416   kfree(lli_in_array);
1417
1418 end_function:
1419
1420   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1421 "SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n",
1422 (int)result);
1423
1424   return result;
1425
1426 }
1427
1428
1429 /*
1430  This function creates the input and output dma tables for
1431  symmetric operations (AES/DES) according to the block size from LLI arays
1432 */
1433 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t    *lli_in_array,
1434                                         unsigned long   sep_in_lli_entries,
1435                                         struct sep_lli_entry_t  *lli_out_array,
1436                                         unsigned long   sep_out_lli_entries,
1437                                         unsigned long   block_size,
1438                                         unsigned long   *lli_table_in_ptr,
1439                                         unsigned long   *lli_table_out_ptr,
1440                                         unsigned long   *in_num_entries_ptr,
1441                                         unsigned long   *out_num_entries_ptr,
1442                                         unsigned long   *table_data_size_ptr)
1443 {
1444   /* points to the area where next lli table can be allocated */
1445   unsigned long lli_table_alloc_addr;
1446
1447   /* input lli table */
1448   struct sep_lli_entry_t                *in_lli_table_ptr;
1449
1450   /* output lli table */
1451   struct sep_lli_entry_t                *out_lli_table_ptr;
1452
1453   /* pointer to the info entry of the table - the last entry */
1454   struct sep_lli_entry_t                *info_in_entry_ptr;
1455
1456   /* pointer to the info entry of the table - the last entry */
1457   struct sep_lli_entry_t                *info_out_entry_ptr;
1458
1459   /* points to the first entry to be processed in the lli_in_array */
1460   unsigned long current_in_entry;
1461
1462   /* points to the first entry to be processed in the lli_out_array */
1463   unsigned long current_out_entry;
1464
1465   /* max size of the input table */
1466   unsigned long in_table_data_size;
1467
1468   /* max size of the output table */
1469   unsigned long out_table_data_size;
1470
1471   /* flag te signifies if this is the first tables build from the arrays */
1472   unsigned long   first_table_flag;
1473
1474   /* the data size that should be in table */
1475   unsigned long table_data_size;
1476
1477   /* number of etnries in the input table */
1478   unsigned long num_entries_in_table;
1479
1480   /* number of etnries in the output table */
1481   unsigned long num_entries_out_table;
1482
1483   /*---------------------
1484         CODE
1485   ------------------------*/
1486
1487   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1488         "SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1489
1490   /* initiate to pint after the message area */
1491   lli_table_alloc_addr = sep_dev->shared_area_addr +
1492         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1493
1494   current_in_entry = 0;
1495   current_out_entry = 0;
1496   first_table_flag = 1;
1497   info_in_entry_ptr = 0;
1498   info_out_entry_ptr = 0;
1499
1500   /* loop till all the entries in in array are not processed */
1501   while (current_in_entry < sep_in_lli_entries) {
1502         /* set the new input and output tables */
1503         in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1504
1505         lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1506                         SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1507
1508         /* set the first output tables */
1509         out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1510
1511         lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1512                                 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1513
1514         /* calculate the maximum size of data for input table */
1515         in_table_data_size =
1516                         sep_calculate_lli_table_max_size(
1517                         &lli_in_array[current_in_entry],
1518                         (sep_in_lli_entries - current_in_entry));
1519
1520         /* calculate the maximum size of data for output table */
1521         out_table_data_size =
1522                         sep_calculate_lli_table_max_size(
1523                         &lli_out_array[current_out_entry],
1524                         (sep_out_lli_entries - current_out_entry));
1525
1526         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1527         "SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1528         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1529         "SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1530
1531         /* check where the data is smallest */
1532         table_data_size = in_table_data_size;
1533         if (table_data_size > out_table_data_size)
1534         table_data_size = out_table_data_size;
1535
1536         /* now calculate the table size so that it will be module block size */
1537         table_data_size = (table_data_size / block_size) * block_size;
1538
1539         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1540                 "SEP Driver:table_data_size is %lu\n",
1541                 table_data_size);
1542
1543         /* construct input lli table */
1544         sep_build_lli_table(&lli_in_array[current_in_entry],
1545                                                 in_lli_table_ptr,
1546                                                 &current_in_entry,
1547                                                 &num_entries_in_table,
1548                                                 table_data_size);
1549
1550         /* construct output lli table */
1551         sep_build_lli_table(&lli_out_array[current_out_entry],
1552                                                 out_lli_table_ptr,
1553                                                 &current_out_entry,
1554                                                 &num_entries_out_table,
1555                                                 table_data_size);
1556
1557         /* if info entry is null - this is the first table built */
1558         if (info_in_entry_ptr == 0) {
1559           /* set the output parameters to physical addresses */
1560           *lli_table_in_ptr =
1561                 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1562           *in_num_entries_ptr = num_entries_in_table;
1563           *lli_table_out_ptr =
1564                 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1565           *out_num_entries_ptr = num_entries_out_table;
1566           *table_data_size_ptr = table_data_size;
1567
1568         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1569         "SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1570         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1571         "SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1572         } else {
1573           /* update the info entry of the previous in table */
1574         info_in_entry_ptr->physical_address =
1575                 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1576         info_in_entry_ptr->block_size =
1577                 ((num_entries_in_table) << 24) | (table_data_size);
1578
1579           /* update the info entry of the previous in table */
1580         info_out_entry_ptr->physical_address =
1581                 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1582         info_out_entry_ptr->block_size =
1583                 ((num_entries_out_table) << 24) | (table_data_size);
1584         }
1585
1586         /* save the pointer to the info entry of the current tables */
1587         info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1588         info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1589
1590         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1591                 "SEP Driver:output num_entries_out_table is %lu\n",
1592                 (unsigned long)num_entries_out_table);
1593         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1594                 "SEP Driver:output info_in_entry_ptr is %lu\n",
1595                 (unsigned long)info_in_entry_ptr);
1596         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1597                 "SEP Driver:output info_out_entry_ptr is %lu\n",
1598                 (unsigned long)info_out_entry_ptr);
1599   }
1600
1601   /* print input tables */
1602   sep_debug_print_lli_tables(
1603         (struct sep_lli_entry_t *)
1604         sep_shared_area_phys_to_virt(*lli_table_in_ptr),
1605         *in_num_entries_ptr,
1606         *table_data_size_ptr);
1607
1608   /* print output tables */
1609   sep_debug_print_lli_tables(
1610         (struct sep_lli_entry_t *)
1611         sep_shared_area_phys_to_virt(*lli_table_out_ptr),
1612         *out_num_entries_ptr,
1613         *table_data_size_ptr);
1614
1615   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1616         "SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1617
1618   return 0;
1619 }
1620
1621 /*
1622   this function calculates the size of data that can be inserted into the lli
1623   table from this array the condition is that either the table is full
1624   (all etnries are entered), or there are no more entries in the lli array
1625 */
1626 unsigned long sep_calculate_lli_table_max_size(
1627                         struct sep_lli_entry_t  *lli_in_array_ptr,
1628                         unsigned long   num_array_entries)
1629 {
1630   /* table data size */
1631   unsigned long table_data_size;
1632
1633   /* counter */
1634   unsigned long counter;
1635
1636   /*---------------------
1637         CODE
1638   ----------------------*/
1639
1640   table_data_size = 0;
1641
1642   /* calculate the data in the out lli table if till we fill the whole
1643   table or till the data has ended */
1644   for (counter = 0;
1645         (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
1646         (counter < num_array_entries); counter++)
1647         table_data_size += lli_in_array_ptr[counter].block_size;
1648
1649   return table_data_size;
1650 }
1651
1652 /*
1653   this functions builds ont lli table from the lli_array according to
1654   the given size of data
1655 */
1656 static void sep_build_lli_table(struct sep_lli_entry_t  *lli_array_ptr,
1657                                 struct sep_lli_entry_t  *lli_table_ptr,
1658                                 unsigned long   *num_processed_entries_ptr,
1659                                 unsigned long   *num_table_entries_ptr,
1660                                 unsigned long   table_data_size)
1661 {
1662   /* current table data size */
1663   unsigned long curr_table_data_size;
1664
1665   /* counter of lli array entry */
1666   unsigned long array_counter;
1667
1668   /*-----------------------
1669         CODE
1670   ---------------------------*/
1671
1672   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1673                 "SEP Driver:--------> sep_build_lli_table start\n");
1674
1675   /* init currrent table data size and lli array entry counter */
1676   curr_table_data_size = 0;
1677   array_counter = 0;
1678   *num_table_entries_ptr = 1;
1679
1680   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1681   "SEP Driver:table_data_size is %lu\n",
1682         table_data_size);
1683
1684   /* fill the table till table size reaches the needed amount */
1685   while (curr_table_data_size < table_data_size) {
1686         /* update the number of entries in table */
1687         (*num_table_entries_ptr)++;
1688
1689         lli_table_ptr->physical_address =
1690                 lli_array_ptr[array_counter].physical_address;
1691         lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1692         curr_table_data_size += lli_table_ptr->block_size;
1693
1694         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1695         "SEP Driver:lli_table_ptr is %08lx\n",
1696         (unsigned long)lli_table_ptr);
1697         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1698         "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1699         lli_table_ptr->physical_address);
1700         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1701         "SEP Driver:lli_table_ptr->block_size is %lu\n",
1702         lli_table_ptr->block_size);
1703
1704         /* check for overflow of the table data */
1705         if (curr_table_data_size > table_data_size) {
1706         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1707                 "SEP Driver:curr_table_data_size > table_data_size\n");
1708
1709           /* update the size of block in the table */
1710         lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1711
1712           /* update the physical address in the lli array */
1713         lli_array_ptr[array_counter].physical_address +=
1714                         lli_table_ptr->block_size;
1715
1716           /* update the block size left in the lli array */
1717         lli_array_ptr[array_counter].block_size =
1718                         (curr_table_data_size - table_data_size);
1719         } else
1720           /* advance to the next entry in the lli_array */
1721           array_counter++;
1722
1723         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1724         "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1725         lli_table_ptr->physical_address);
1726         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1727         "SEP Driver:lli_table_ptr->block_size is %lu\n",
1728         lli_table_ptr->block_size);
1729
1730         /* move to the next entry in table */
1731         lli_table_ptr++;
1732   }
1733
1734   /* set the info entry to default */
1735   lli_table_ptr->physical_address = 0xffffffff;
1736   lli_table_ptr->block_size = 0;
1737
1738   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1739         "SEP Driver:lli_table_ptr is %08lx\n",
1740         (unsigned long)lli_table_ptr);
1741   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1742         "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1743         lli_table_ptr->physical_address);
1744   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1745         "SEP Driver:lli_table_ptr->block_size is %lu\n",
1746         lli_table_ptr->block_size);
1747
1748
1749   /* set the output parameter */
1750   *num_processed_entries_ptr += array_counter;
1751
1752   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1753         "SEP Driver:*num_processed_entries_ptr is %lu\n",
1754         *num_processed_entries_ptr);
1755
1756
1757   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1758                 "SEP Driver:<-------- sep_build_lli_table end\n");
1759
1760   return;
1761 }
1762
1763 /*
1764   this function goes over the list of the print created tables and
1765   prints all the data
1766 */
1767 static void sep_debug_print_lli_tables(struct sep_lli_entry_t   *lli_table_ptr,
1768                                         unsigned long   num_table_entries,
1769                                         unsigned long   table_data_size)
1770 {
1771   unsigned long table_count;
1772
1773   unsigned long entries_count;
1774   /*-----------------------------
1775         CODE
1776   -------------------------------*/
1777
1778   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1779                 "SEP Driver:--------> sep_debug_print_lli_tables start\n");
1780
1781   table_count = 1;
1782   while ((unsigned long)lli_table_ptr != 0xffffffff) {
1783         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1784         "SEP Driver: lli table %08lx, table_data_size is %lu\n",
1785         table_count,
1786         table_data_size);
1787         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1788         "SEP Driver: num_table_entries is %lu\n", num_table_entries);
1789
1790         /* print entries of the table (without info entry) */
1791         for (entries_count = 0;
1792                 entries_count < num_table_entries;
1793                 entries_count++, lli_table_ptr++) {
1794                 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1795                 "SEP Driver:lli_table_ptr address is %08lx\n",
1796                 (unsigned long)lli_table_ptr);
1797                 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1798                 "SEP Driver:phys address is %08lx block size is %lu\n",
1799                 lli_table_ptr->physical_address, lli_table_ptr->block_size);
1800         }
1801
1802         /* point to the info entry */
1803         lli_table_ptr--;
1804
1805         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1806         "SEP Driver:phys lli_table_ptr->block_size is %lu\n",
1807         lli_table_ptr->block_size);
1808         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1809         "SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
1810         lli_table_ptr->physical_address);
1811
1812
1813         table_data_size = lli_table_ptr->block_size & 0xffffff;
1814         num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1815         lli_table_ptr = (struct sep_lli_entry_t *)
1816                                 (lli_table_ptr->physical_address);
1817
1818         DEBUG_PRINT_3(SEP_DEBUG_LEVEL_EXTENDED,
1819         "SEP Driver:phys table_data_size is %lu num_table_entries is \
1820         %lu lli_table_ptr is%lu\n",
1821         table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
1822
1823         if ((unsigned long)lli_table_ptr != 0xffffffff)
1824         lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
1825                                         (unsigned long)lli_table_ptr);
1826
1827         table_count++;
1828   }
1829
1830   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1831                 "SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1832 }
1833
1834
1835 /*
1836   This function locks all the physical pages of the application virtual buffer
1837   and construct a basic lli  array, where each entry holds the physical page
1838   address and the size that application data holds in this physical pages
1839 */
1840 int sep_lock_user_pages(unsigned long           app_virt_addr,
1841                         unsigned long           data_size,
1842                         unsigned long           *num_pages_ptr,
1843                         struct sep_lli_entry_t          **lli_array_ptr,
1844                         struct page             ***page_array_ptr)
1845
1846 {
1847   /* error */
1848   int                           error;
1849
1850   /* the the page of the end address of the user space buffer */
1851   unsigned long         end_page;
1852
1853   /* the page of the start address of the user space buffer */
1854   unsigned long         start_page;
1855
1856   /* the range in pages */
1857   unsigned long         num_pages;
1858
1859   /* array of pointers ot page */
1860   struct page           **page_array;
1861
1862   /* array of lli */
1863   struct sep_lli_entry_t                *lli_array;
1864
1865   /* count */
1866   unsigned long         count;
1867
1868   /* result */
1869   int                           result;
1870
1871   /*------------------------
1872         CODE
1873   --------------------------*/
1874
1875   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1876                 "SEP Driver:--------> sep_lock_user_pages start\n");
1877
1878   error = 0;
1879
1880   /* set start and end pages  and num pages */
1881   end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1882   start_page = app_virt_addr >> PAGE_SHIFT;
1883   num_pages = end_page - start_page + 1;
1884
1885   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1886         "SEP Driver: app_virt_addr is %08lx\n",
1887         app_virt_addr);
1888   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1889         "SEP Driver: data_size is %lu\n",
1890         data_size);
1891   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1892         "SEP Driver: start_page is %lu\n",
1893         start_page);
1894   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1895         "SEP Driver: end_page is %lu\n",
1896         end_page);
1897   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1898         "SEP Driver: num_pages is %lu\n",
1899         num_pages);
1900
1901   /* allocate array of pages structure pointers */
1902   page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1903   if (!page_array) {
1904         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1905                 "SEP Driver: kmalloc for page_array failed\n");
1906
1907         error = -ENOMEM;
1908         goto end_function;
1909   }
1910
1911   lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1912   if (!lli_array) {
1913         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1914                 "SEP Driver: kmalloc for lli_array failed\n");
1915
1916         error = -ENOMEM;
1917         goto end_function_with_error1;
1918   }
1919
1920   /* convert the application virtual address into a set of physical */
1921   down_read(&current->mm->mmap_sem);
1922   result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
1923         page_array,
1924         0);
1925   up_read(&current->mm->mmap_sem);
1926
1927   /* check the number of pages locked - if not all then exit with error */
1928   if (result != num_pages) {
1929         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1930                 "SEP Driver: not all pages locked by get_user_pages\n");
1931
1932         error = -ENOMEM;
1933         goto end_function_with_error2;
1934   }
1935
1936   /* flush the cache */
1937   for (count = 0; count < num_pages; count++)
1938         flush_dcache_page(page_array[count]);
1939
1940   /* set the start address of the first page - app data may start not at
1941         the beginning of the page */
1942   lli_array[0].physical_address = (
1943                         (unsigned long)page_to_phys(page_array[0])) +
1944                         (app_virt_addr & (~PAGE_MASK)) ;
1945
1946   /* check that not all the data is in the first page only */
1947   if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1948         lli_array[0].block_size = data_size;
1949   else
1950         lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1951
1952   /* debug print */
1953   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1954   "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
1955         lli_array[0].physical_address,
1956         lli_array[0].block_size);
1957
1958   /* go from the second page to the prev before last */
1959   for (count = 1; count < (num_pages - 1); count++) {
1960         lli_array[count].physical_address =
1961                 (unsigned long)page_to_phys(page_array[count]);
1962         lli_array[count].block_size = PAGE_SIZE;
1963
1964         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1965         "lli_array[%lu].physical_address is %08lx, \
1966         lli_array[%lu].block_size is %lu\n",
1967         count, lli_array[count].physical_address,
1968         count,
1969         lli_array[count].block_size);
1970   }
1971
1972   /* if more then 1 pages locked - then update for the last page size needed */
1973   if (num_pages > 1) {
1974         /* update the address of the last page */
1975         lli_array[count].physical_address =
1976                 (unsigned long)page_to_phys(page_array[count]);
1977
1978         /* set the size of the last page */
1979         lli_array[count].block_size = (app_virt_addr + data_size) &
1980                                         (~PAGE_MASK);
1981
1982         if (lli_array[count].block_size == 0) {
1983         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1984         "app_virt_addr is %08lx\n",
1985         app_virt_addr);
1986         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
1987           while (1);
1988         }
1989         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1990         "lli_array[%lu].physical_address is %08lx, \
1991                 lli_array[%lu].block_size is %lu\n",
1992         count, lli_array[count].physical_address,
1993         count,
1994         lli_array[count].block_size);
1995   }
1996
1997   /* set output params */
1998   *lli_array_ptr = lli_array;
1999   *num_pages_ptr = num_pages;
2000   *page_array_ptr = page_array;
2001
2002   goto end_function;
2003
2004 end_function_with_error2:
2005
2006   /* release the cache */
2007   for (count = 0; count < num_pages; count++)
2008         page_cache_release(page_array[count]);
2009
2010   /* free lli array */
2011   kfree(lli_array);
2012
2013 end_function_with_error1:
2014
2015   /* free page array */
2016   kfree(page_array);
2017
2018 end_function:
2019
2020   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2021                 "SEP Driver:<-------- sep_lock_user_pages end\n");
2022
2023   return 0;
2024 }
2025
2026 /*
2027   This function locks all the physical pages of the kernel virtual buffer
2028   and construct a basic lli  array, where each entry holds the physical
2029   page address and the size that application data holds in this physical pages
2030 */
2031 int sep_lock_kernel_pages(unsigned long         kernel_virt_addr,
2032                         unsigned long           data_size,
2033                         unsigned long           *num_pages_ptr,
2034                         struct sep_lli_entry_t          **lli_array_ptr,
2035                         struct page             ***page_array_ptr)
2036
2037 {
2038   /* error */
2039   int                           error;
2040
2041   /* the the page of the end address of the user space buffer */
2042   unsigned long         end_page;
2043
2044   /* the page of the start address of the user space buffer */
2045   unsigned long         start_page;
2046
2047   /* the range in pages */
2048   unsigned long         num_pages;
2049
2050   /* array of lli */
2051   struct sep_lli_entry_t                *lli_array;
2052
2053   /* next kernel address to map */
2054   unsigned long         next_kernel_address;
2055
2056   /* count */
2057   unsigned long         count;
2058
2059
2060   /*------------------------
2061         CODE
2062   --------------------------*/
2063
2064   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2065                 "SEP Driver:--------> sep_lock_kernel_pages start\n");
2066
2067   error = 0;
2068
2069   /* set start and end pages  and num pages */
2070   end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
2071   start_page = kernel_virt_addr >> PAGE_SHIFT;
2072   num_pages = end_page - start_page + 1;
2073
2074   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2075         "SEP Driver: kernel_virt_addr is %08lx\n",
2076         kernel_virt_addr);
2077   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2078         "SEP Driver: data_size is %lu\n",
2079         data_size);
2080   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2081         "SEP Driver: start_page is %lx\n",
2082         start_page);
2083   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2084         "SEP Driver: end_page is %lx\n",
2085         end_page);
2086   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2087         "SEP Driver: num_pages is %lu\n",
2088         num_pages);
2089
2090   lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
2091   if (!lli_array) {
2092         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
2093                 "SEP Driver: kmalloc for lli_array failed\n");
2094
2095         error = -ENOMEM;
2096         goto end_function;
2097   }
2098
2099   /* set the start address of the first page - app data may start not at
2100   the beginning of the page */
2101   lli_array[0].physical_address =
2102         (unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
2103
2104   /* check that not all the data is in the first page only */
2105   if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
2106         lli_array[0].block_size = data_size;
2107   else
2108         lli_array[0].block_size =
2109                 PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
2110
2111   /* debug print */
2112   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2113   "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
2114         lli_array[0].physical_address,
2115         lli_array[0].block_size);
2116
2117   /* advance the address to the start of the next page */
2118   next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
2119
2120   /* go from the second page to the prev before last */
2121   for (count = 1; count < (num_pages - 1); count++) {
2122         lli_array[count].physical_address =
2123         (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2124         lli_array[count].block_size = PAGE_SIZE;
2125
2126         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2127         "lli_array[%lu].physical_address is %08lx, \
2128         lli_array[%lu].block_size is %lu\n",
2129         count, lli_array[count].physical_address, count,
2130         lli_array[count].block_size);
2131
2132         next_kernel_address += PAGE_SIZE;
2133   }
2134
2135   /* if more then 1 pages locked - then update for the last page size needed */
2136   if (num_pages > 1) {
2137         /* update the address of the last page */
2138         lli_array[count].physical_address =
2139         (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2140
2141         /* set the size of the last page */
2142         lli_array[count].block_size =
2143                 (kernel_virt_addr + data_size) & (~PAGE_MASK);
2144
2145         if (lli_array[count].block_size == 0) {
2146         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
2147         "app_virt_addr is %08lx\n",
2148         kernel_virt_addr);
2149         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
2150           while (1);
2151         }
2152
2153         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2154         "lli_array[%lu].physical_address is %08lx, \
2155         lli_array[%lu].block_size is %lu\n",
2156         count, lli_array[count].physical_address,
2157         count,
2158         lli_array[count].block_size);
2159   }
2160
2161   /* set output params */
2162   *lli_array_ptr = lli_array;
2163   *num_pages_ptr = num_pages;
2164   *page_array_ptr = 0;
2165
2166
2167 end_function:
2168
2169   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2170                 "SEP Driver:<-------- sep_lock_kernel_pages end\n");
2171
2172   return 0;
2173 }
2174
2175 /*
2176   This function releases all the application virtual buffer physical pages,
2177         that were previously locked
2178 */
2179 int sep_free_dma_pages(struct page      **page_array_ptr,
2180                                         unsigned long num_pages,
2181                                         unsigned long dirtyFlag)
2182 {
2183   /* count */
2184   unsigned long count;
2185
2186   /*-------------------
2187         CODE
2188   ---------------------*/
2189
2190   if (dirtyFlag) {
2191         for (count = 0; count < num_pages; count++) {
2192           /* the out array was written, therefore the data was changed */
2193         if (!PageReserved(page_array_ptr[count]))
2194                 SetPageDirty(page_array_ptr[count]);
2195           page_cache_release(page_array_ptr[count]);
2196         }
2197   } else {
2198         /* free in pages - the data was only read, therefore no update was done
2199                 on those pages */
2200         for (count = 0; count < num_pages; count++)
2201           page_cache_release(page_array_ptr[count]);
2202   }
2203
2204   if (page_array_ptr)
2205         /* free the array */
2206         kfree(page_array_ptr);
2207
2208   return 0;
2209 }
2210
2211 /*
2212   This function raises interrupt to SEP that signals that is has a new
2213         command from HOST
2214 */
2215 static void sep_send_command_handler()
2216 {
2217
2218   unsigned long count;
2219
2220   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2221                 "SEP Driver:--------> sep_send_command_handler start\n");
2222
2223   sep_set_time(0, 0);
2224
2225   /* flash cache */
2226   flush_cache_all();
2227
2228   for (count = 0; count < 12 * 4; count += 4)
2229         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2230         "Word %lu of the message is %lu\n",
2231         count,
2232         *((unsigned long *)(sep_dev->shared_area_addr + count)));
2233
2234   /* update counter */
2235   sep_dev->host_to_sep_send_counter++;
2236
2237   /* send interrupt to SEP */
2238   SEP_WRITE_REGISTER(sep_dev->reg_base_address +
2239                         HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2240
2241   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2242                 "SEP Driver:<-------- sep_send_command_handler end\n");
2243
2244   return;
2245 }
2246
2247 /*
2248   This function raises interrupt to SEPm that signals that is has a
2249   new command from HOST
2250 */
2251 static void sep_send_reply_command_handler()
2252 {
2253   unsigned long count;
2254
2255   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2256                 "SEP Driver:--------> sep_send_reply_command_handler start\n");
2257
2258   /* flash cache */
2259   flush_cache_all();
2260
2261   for (count = 0; count < 12 * 4; count += 4)
2262         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2263         "Word %lu of the message is %lu\n",
2264         count,
2265         *((unsigned long *)(sep_dev->shared_area_addr + count)));
2266
2267
2268   /* update counter */
2269   sep_dev->host_to_sep_send_counter++;
2270
2271   /* send the interrupt to SEP */
2272   SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_HOST_SEP_GPR2_REG_ADDR,
2273                                 sep_dev->host_to_sep_send_counter);
2274
2275   /* update both counters */
2276   sep_dev->host_to_sep_send_counter++;
2277
2278   sep_dev->sep_to_host_reply_counter++;
2279
2280   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2281                 "SEP Driver:<-------- sep_send_reply_command_handler end\n");
2282
2283   return;
2284 }
2285
2286
2287
2288 /*
2289   This function handles the allocate data pool memory request
2290   This function returns calculates the physical address of the
2291   allocated memory, and the offset of this area from the mapped address.
2292   Therefore, the FVOs in user space can calculate the exact virtual
2293   address of this allocated memory
2294 */
2295 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
2296 {
2297   /* error */
2298   int                           error;
2299
2300   /* command paramaters */
2301   struct sep_driver_alloc_t  command_args;
2302
2303   /*-------------------------
2304         CODE
2305   ----------------------------*/
2306
2307   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2308         "SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
2309
2310
2311   error = copy_from_user(&command_args,
2312         (void *)arg,
2313         sizeof(struct sep_driver_alloc_t));
2314   if (error)
2315         goto end_function;
2316
2317   /* allocate memory */
2318   if (
2319         (sep_dev->data_pool_bytes_allocated + command_args.num_bytes) >
2320         SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
2321         error = -ENOTTY;
2322         goto end_function;
2323   }
2324
2325   /* set the virtual and physical address */
2326   command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2327                         sep_dev->data_pool_bytes_allocated;
2328   command_args.phys_address = sep_dev->phys_shared_area_addr +
2329                         SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2330                         sep_dev->data_pool_bytes_allocated;
2331
2332   /* write the memory back to the user space */
2333   error = copy_to_user((void *)arg,
2334         (void *)&command_args,
2335         sizeof(struct sep_driver_alloc_t));
2336   if (error)
2337         goto end_function;
2338
2339   /* set the allocation */
2340   sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
2341
2342 end_function:
2343
2344   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2345         "SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
2346
2347   return error;
2348 }
2349
2350 /*
2351   This function  handles write into allocated data pool command
2352 */
2353 static int sep_write_into_data_pool_handler(unsigned long arg)
2354 {
2355   /* error */
2356   int                   error;
2357
2358   /* virtual address */
2359   unsigned long virt_address;
2360
2361   /* application in address */
2362   unsigned long app_in_address;
2363
2364   /* number of bytes */
2365   unsigned long num_bytes;
2366
2367   /* address of the data pool */
2368   unsigned long data_pool_area_addr;
2369
2370   /*--------------------------
2371         CODE
2372   -----------------------------*/
2373
2374   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2375         "SEP Driver:--------> sep_write_into_data_pool_handler start\n");
2376
2377   /* get the application address */
2378   error = get_user(app_in_address,
2379                 &(((struct sep_driver_write_t *)arg)->app_address));
2380   if (error)
2381         goto end_function;
2382
2383   /* get the virtual kernel address address */
2384   error = get_user(virt_address,
2385                 &(((struct sep_driver_write_t *)arg)->datapool_address));
2386   if (error)
2387         goto end_function;
2388
2389   /* get the number of bytes */
2390   error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2391   if (error)
2392         goto end_function;
2393
2394   /* calculate the start of the data pool */
2395   data_pool_area_addr = sep_dev->shared_area_addr +
2396                         SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2397
2398
2399   /* check that the range of the virtual kernel address is correct */
2400   if ((virt_address < data_pool_area_addr) ||
2401           (virt_address > (data_pool_area_addr +
2402           SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2403         error = -ENOTTY;
2404         goto end_function;
2405   }
2406
2407   /* copy the application data */
2408   error = copy_from_user((void *)virt_address,
2409         (void *)app_in_address,
2410         num_bytes);
2411
2412 end_function:
2413
2414   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2415                 "SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
2416
2417   return error;
2418 }
2419
2420 /*
2421   this function handles the read from data pool command
2422 */
2423 static int sep_read_from_data_pool_handler(unsigned long arg)
2424 {
2425   /* error */
2426   int                   error;
2427
2428   /* virtual address of dest application buffer */
2429   unsigned long app_out_address;
2430
2431   /* virtual address of the data pool */
2432   unsigned long virt_address;
2433
2434   /* number bytes */
2435   unsigned long num_bytes;
2436
2437   /* address of the data pool */
2438   unsigned long data_pool_area_addr;
2439
2440   /*------------------------
2441         CODE
2442   -----------------------------*/
2443
2444   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2445         "SEP Driver:--------> sep_read_from_data_pool_handler start\n");
2446
2447   /* get the application address */
2448   error = get_user(app_out_address,
2449                 &(((struct sep_driver_write_t *)arg)->app_address));
2450   if (error)
2451         goto end_function;
2452
2453   /* get the virtual kernel address address */
2454   error = get_user(virt_address,
2455         &(((struct sep_driver_write_t *)arg)->datapool_address));
2456   if (error)
2457         goto end_function;
2458
2459   /* get the number of bytes */
2460   error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2461   if (error)
2462         goto end_function;
2463
2464   /* calculate the start of the data pool */
2465   data_pool_area_addr = sep_dev->shared_area_addr +
2466                         SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2467
2468   /* check that the range of the virtual kernel address is correct */
2469   if ((virt_address < data_pool_area_addr) ||
2470           (virt_address > (data_pool_area_addr +
2471           SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2472         error = -ENOTTY;
2473         goto end_function;
2474   }
2475
2476   /* copy the application data */
2477   error = copy_to_user((void *)app_out_address, (void *)virt_address,
2478   num_bytes);
2479
2480 end_function:
2481
2482   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2483                 "SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
2484
2485   return error;
2486 }
2487
2488
2489 /*
2490   this function handles tha request for creation of the DMA table
2491   for the synchronic symmetric operations (AES,DES)
2492 */
2493 static int sep_create_sync_dma_tables_handler(unsigned long arg)
2494 {
2495   /* error */
2496   int                                                   error;
2497
2498   /* command arguments */
2499   struct sep_driver_build_sync_table_t command_args;
2500
2501   /*------------------------
2502         CODE
2503   --------------------------*/
2504
2505   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2506         "SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
2507
2508   error = copy_from_user(&command_args,
2509         (void *)arg,
2510         sizeof(struct sep_driver_build_sync_table_t));
2511   if (error)
2512         goto end_function;
2513
2514   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2515         "app_in_address is %08lx\n",
2516         command_args.app_in_address);
2517   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2518         "app_out_address is %08lx\n",
2519         command_args.app_out_address);
2520   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2521         "data_size is %lu\n",
2522         command_args.data_in_size);
2523   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2524         "block_size is %lu\n",
2525         command_args.block_size);
2526
2527
2528   /* check if we need to build only input table or input/output */
2529   if (command_args.app_out_address)
2530         /* prepare input and output tables */
2531         error = sep_prepare_input_output_dma_table(command_args.app_in_address,
2532                                         command_args.app_out_address,
2533                                         command_args.data_in_size,
2534                                         command_args.block_size,
2535                                         &command_args.in_table_address,
2536                                         &command_args.out_table_address,
2537                                         &command_args.in_table_num_entries,
2538                                         &command_args.out_table_num_entries,
2539                                         &command_args.table_data_size,
2540                                         command_args.isKernelVirtualAddress);
2541   else
2542         /* prepare input tables */
2543         error = sep_prepare_input_dma_table(command_args.app_in_address,
2544                                         command_args.data_in_size,
2545                                         command_args.block_size,
2546                                         &command_args.in_table_address,
2547                                         &command_args.in_table_num_entries,
2548                                         &command_args.table_data_size,
2549                                         command_args.isKernelVirtualAddress);
2550
2551   if (error)
2552         goto end_function;
2553
2554   /* copy to user */
2555   error = copy_to_user((void *)arg,
2556         (void *)&command_args,
2557         sizeof(struct sep_driver_build_sync_table_t));
2558
2559 end_function:
2560
2561   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2562         "SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
2563
2564   return error;
2565 }
2566
2567 /*
2568   this function handles the request for freeing dma table for synhronic actions
2569 */
2570 int sep_free_dma_table_data_handler()
2571 {
2572   /*-------------------------
2573         CODE
2574   -----------------------------*/
2575
2576   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2577         "SEP Driver:--------> sep_free_dma_table_data_handler start\n");
2578
2579   /* free input pages array */
2580   sep_free_dma_pages(sep_dev->in_page_array,
2581                                         sep_dev->in_num_pages,
2582                                          0);
2583
2584   /* free output pages array if needed */
2585   if (sep_dev->out_page_array)
2586         sep_free_dma_pages(sep_dev->out_page_array,
2587                                                 sep_dev->out_num_pages,
2588                                                 1);
2589
2590   /* reset all the values */
2591   sep_dev->in_page_array = 0;
2592   sep_dev->out_page_array = 0;
2593   sep_dev->in_num_pages = 0;
2594   sep_dev->out_num_pages = 0;
2595
2596
2597   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2598                 "SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
2599
2600   return 0;
2601 }
2602
2603 /*
2604   this function handles the request to create the DMA tables for flow
2605 */
2606 static int sep_create_flow_dma_tables_handler(unsigned long arg)
2607 {
2608   /* error */
2609   int                                                   error;
2610
2611   /* command arguments */
2612   struct sep_driver_build_flow_table_t  command_args;
2613
2614   /* first table - output */
2615   struct sep_lli_entry_t                                 first_table_data;
2616
2617   /* dma table data */
2618   struct sep_lli_entry_t                                last_table_data;
2619
2620   /* pointer to the info entry of the previuos DMA table */
2621   struct sep_lli_entry_t                *prev_info_entry_ptr;
2622
2623   /* pointer to the flow data strucutre */
2624   struct sep_flow_context_t             *flow_context_ptr;
2625
2626   /*------------------------
2627         CODE
2628   --------------------------*/
2629
2630   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2631         "SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
2632
2633   /* init variables */
2634   prev_info_entry_ptr = 0;
2635   first_table_data.physical_address = 0xffffffff;
2636
2637   /* find the free structure for flow data */
2638   error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
2639   if (error)
2640         goto end_function;
2641
2642   error = copy_from_user(&command_args,
2643         (void *)arg,
2644         sizeof(struct sep_driver_build_flow_table_t));
2645   if (error)
2646         goto end_function;
2647
2648   /* create flow tables */
2649   error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2650                                         command_args.virt_buff_data_addr,
2651                                         flow_context_ptr,
2652                                         &first_table_data,
2653                                         &last_table_data,
2654                                         command_args.isKernelVirtualAddress);
2655   if (error)
2656         goto end_function_with_error;
2657
2658   /* check if flow is static */
2659   if (!command_args.flow_type)
2660         /* point the info entry of the last to the info entry of the first */
2661         last_table_data = first_table_data;
2662
2663   /* set output params */
2664   command_args.first_table_addr = first_table_data.physical_address;
2665   command_args.first_table_num_entries =
2666         ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
2667         SEP_NUM_ENTRIES_MASK);
2668   command_args.first_table_data_size =
2669         (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2670
2671   /* send the parameters to user application */
2672   error = copy_to_user((void *)arg,
2673         &command_args,
2674         sizeof(struct sep_driver_build_flow_table_t));
2675   if (error)
2676         goto end_function_with_error;
2677
2678   /* all the flow created  - update the flow entry with temp id */
2679   flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
2680
2681   /* set the processing tables data in the context */
2682   if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
2683         flow_context_ptr->input_tables_in_process = first_table_data;
2684   else
2685         flow_context_ptr->output_tables_in_process = first_table_data;
2686
2687   goto end_function;
2688
2689 end_function_with_error:
2690
2691   /* free the allocated tables */
2692   sep_deallocated_flow_tables(&first_table_data);
2693
2694 end_function:
2695
2696   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2697         "SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
2698
2699   return error;
2700
2701 }
2702
2703 /*
2704   this functio n handles add tables to flow
2705 */
2706 static int sep_add_flow_tables_handler(unsigned long arg)
2707 {
2708   /* error */
2709   int                                                   error;
2710
2711   /* number of entries */
2712   unsigned long                         num_entries;
2713
2714   /* command arguments */
2715   struct sep_driver_add_flow_table_t    command_args;
2716
2717   /* pointer to the flow data strucutre */
2718   struct sep_flow_context_t             *flow_context_ptr;
2719
2720   /* first dma table data */
2721   struct sep_lli_entry_t                first_table_data;
2722
2723   /* last dma table data */
2724   struct sep_lli_entry_t                last_table_data;
2725
2726   /* pointer to the info entry of the current DMA table */
2727   struct sep_lli_entry_t                *info_entry_ptr;
2728
2729   /*--------------------------
2730         CODE
2731   ----------------------------*/
2732
2733   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2734                 "SEP Driver:--------> sep_add_flow_tables_handler start\n");
2735
2736   /* get input parameters */
2737   error = copy_from_user(&command_args,
2738         (void *)arg,
2739         sizeof(struct sep_driver_add_flow_table_t));
2740   if (error)
2741         goto end_function;
2742
2743   /* find the flow structure for the flow id */
2744   error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2745   if (error)
2746         goto end_function;
2747
2748   /* prepare the flow dma tables */
2749   error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2750                                         command_args.virt_buff_data_addr,
2751                                         flow_context_ptr,
2752                                         &first_table_data,
2753                                         &last_table_data,
2754                                         command_args.isKernelVirtualAddress);
2755   if (error)
2756         goto end_function_with_error;
2757
2758   /* now check if there is already an existing add table for this flow */
2759   if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
2760         /* this buffer was for input buffers */
2761         if (flow_context_ptr->input_tables_flag) {
2762           /* add table already exists - add the new tables to the end
2763                 of the previous */
2764         num_entries = (flow_context_ptr->last_input_table.block_size >>
2765                         SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2766
2767         info_entry_ptr =
2768         (struct sep_lli_entry_t *)
2769         (flow_context_ptr->last_input_table.physical_address +
2770         (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2771
2772           /* connect to list of tables */
2773           *info_entry_ptr = first_table_data;
2774
2775           /* set the first table data */
2776           first_table_data = flow_context_ptr->first_input_table;
2777         } else {
2778           /* set the input flag */
2779           flow_context_ptr->input_tables_flag = 1;
2780
2781           /* set the first table data */
2782           flow_context_ptr->first_input_table = first_table_data;
2783         }
2784         /* set the last table data */
2785         flow_context_ptr->last_input_table = last_table_data;
2786   } else  /* this is output tables */ {
2787         /* this buffer was for input buffers */
2788         if (flow_context_ptr->output_tables_flag) {
2789           /* add table already exists - add the new tables to
2790                 the end of the previous */
2791         num_entries = (flow_context_ptr->last_output_table.block_size >>
2792                 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2793
2794         info_entry_ptr =
2795         (struct sep_lli_entry_t *)
2796         (flow_context_ptr->last_output_table.physical_address +
2797         (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2798
2799           /* connect to list of tables */
2800           *info_entry_ptr = first_table_data;
2801
2802           /* set the first table data */
2803           first_table_data = flow_context_ptr->first_output_table;
2804         } else {
2805           /* set the input flag */
2806           flow_context_ptr->output_tables_flag = 1;
2807
2808           /* set the first table data */
2809           flow_context_ptr->first_output_table = first_table_data;
2810         }
2811         /* set the last table data */
2812         flow_context_ptr->last_output_table = last_table_data;
2813   }
2814
2815   /* set output params */
2816   command_args.first_table_addr = first_table_data.physical_address;
2817   command_args.first_table_num_entries = ((first_table_data.block_size >>
2818   SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
2819   command_args.first_table_data_size =
2820   (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2821
2822   /* send the parameters to user application */
2823   error = copy_to_user((void *)arg,
2824         &command_args,
2825         sizeof(struct sep_driver_add_flow_table_t));
2826   if (error)
2827         goto end_function_with_error;
2828
2829 end_function_with_error:
2830
2831   /* free the allocated tables */
2832   sep_deallocated_flow_tables(&first_table_data);
2833
2834 end_function:
2835
2836   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2837                 "SEP Driver:<-------- sep_add_flow_tables_handler end\n");
2838
2839   return error;
2840 }
2841
2842 /*
2843   this function add the flow add message to the specific flow
2844 */
2845 static int sep_add_flow_tables_message_handler(unsigned long arg)
2846 {
2847   /* error */
2848   int                                           error;
2849
2850   /* arguments */
2851   struct sep_driver_add_message_t  command_args;
2852
2853   /* flow context */
2854   struct sep_flow_context_t             *flow_context_ptr;
2855
2856   /*----------------------------
2857         CODE
2858   ------------------------------*/
2859
2860   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2861         "SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
2862
2863   error = copy_from_user(&command_args,
2864         (void *)arg,
2865         sizeof(struct sep_driver_add_message_t));
2866   if (error)
2867         goto end_function;
2868
2869   /* check input */
2870   if (command_args.message_size_in_bytes >
2871         SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
2872         error = -ENOMEM;
2873         goto end_function;
2874   }
2875
2876   /* find the flow context */
2877   error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2878   if (error)
2879         goto end_function;
2880
2881   /* copy the message into context */
2882   flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
2883
2884   error = copy_from_user(flow_context_ptr->message,
2885         (void *)command_args.message_address,
2886         command_args.message_size_in_bytes);
2887
2888
2889 end_function:
2890
2891   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2892         "SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
2893
2894   return error;
2895 }
2896
2897
2898 /*
2899   this function returns the physical and virtual addresses of the static pool
2900 */
2901 static int sep_get_static_pool_addr_handler(unsigned long arg)
2902 {
2903   /* error */
2904   int                                                   error;
2905
2906   /* command arguments */
2907   struct sep_driver_static_pool_addr_t  command_args;
2908
2909   /*-----------------------------
2910         CODE
2911   ------------------------------*/
2912
2913   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2914         "SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2915
2916   /*prepare the output parameters in the struct */
2917   command_args.physical_static_address = sep_dev->phys_shared_area_addr +
2918                                 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2919   command_args.virtual_static_address = sep_dev->shared_area_addr +
2920                                 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2921
2922   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2923  "SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
2924         command_args.physical_static_address,
2925         command_args.virtual_static_address);
2926
2927   /* send the parameters to user application */
2928   error = copy_to_user((void *)arg,
2929         &command_args,
2930         sizeof(struct sep_driver_static_pool_addr_t));
2931   if (error)
2932         goto end_function;
2933
2934 end_function:
2935
2936   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2937                 "SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2938
2939   return error;
2940 }
2941
2942 /*
2943   this address gets the offset of the physical address from the start
2944   of the mapped area
2945 */
2946 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2947 {
2948   /* error */
2949   int                                                   error;
2950
2951   /* command arguments */
2952   struct sep_driver_get_mapped_offset_t command_args;
2953
2954   /*-----------------------------
2955         CODE
2956   ------------------------------*/
2957
2958   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2959         "SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2960
2961   error = copy_from_user(&command_args,
2962         (void *)arg,
2963         sizeof(struct sep_driver_get_mapped_offset_t));
2964   if (error)
2965         goto end_function;
2966
2967   if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2968         error = -ENOTTY;
2969         goto end_function;
2970   }
2971
2972   /*prepare the output parameters in the struct */
2973   command_args.offset = command_args.physical_address -
2974                                         sep_dev->phys_shared_area_addr;
2975
2976   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2977   "SEP Driver:physical_address is %08lx, offset is %lu\n",
2978         command_args.physical_address,
2979         command_args.offset);
2980
2981   /* send the parameters to user application */
2982   error = copy_to_user((void *)arg,
2983         &command_args,
2984         sizeof(struct sep_driver_get_mapped_offset_t));
2985   if (error)
2986         goto end_function;
2987
2988 end_function:
2989
2990   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2991         "SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2992
2993   return error;
2994 }
2995
2996
2997 /*
2998   ?
2999 */
3000 static int sep_start_handler(void)
3001 {
3002   /* reg val */
3003   unsigned long reg_val;
3004
3005   /* error */
3006   unsigned long error;
3007
3008   /*-----------------------------
3009         CODE
3010   ------------------------------*/
3011
3012   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3013                 "SEP Driver:--------> sep_start_handler start\n");
3014
3015   error = 0;
3016
3017   /* wait in polling for message from SEP */
3018   do {
3019         SEP_READ_REGISTER(sep_dev->reg_base_address +
3020                         HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
3021   } while (!reg_val);
3022
3023   /* check the value */
3024   if (reg_val == 0x1) {
3025         /* fatal error - read erro status from GPRO */
3026         SEP_READ_REGISTER(sep_dev->reg_base_address +
3027                                 HW_HOST_SEP_HOST_GPR0_REG_ADDR, error);
3028         goto end_function;
3029   }
3030
3031 end_function:
3032
3033   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3034                 "SEP Driver:<-------- sep_start_handler end\n");
3035
3036   return error;
3037 }
3038
3039 /*
3040   this function handles the request for SEP initialization
3041 */
3042 static int sep_init_handler(unsigned long arg)
3043 {
3044   /* word from message */
3045   unsigned long  message_word;
3046
3047   /* message ptr */
3048   unsigned long         *message_ptr;
3049
3050   /* command arguments */
3051   struct sep_driver_init_t command_args;
3052
3053   /* counter */
3054   unsigned long counter;
3055
3056   /* error */
3057   unsigned long error;
3058
3059   /* reg val */
3060   unsigned long reg_val;
3061
3062   /*-------------------
3063         CODE
3064   ---------------------*/
3065
3066   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3067                 "SEP Driver:--------> sep_init_handler start\n");
3068
3069   error = 0;
3070
3071   error = copy_from_user(&command_args, (void *)arg,
3072                         sizeof(struct sep_driver_init_t));
3073
3074   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3075                 "SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
3076
3077   if (error)
3078         goto end_function;
3079
3080   /* PATCH - configure the DMA to single -burst instead of multi-burst */
3081   /*sep_configure_dma_burst();*/
3082
3083   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3084                 "SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
3085
3086   message_ptr = (unsigned long *)command_args.message_addr;
3087
3088   /* set the base address of the SRAM  */
3089   SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3090                                         HW_SRAM_ADDR_REG_ADDR,
3091                                         HW_CC_SRAM_BASE_ADDRESS);
3092
3093   for (counter = 0 ;
3094                 counter < command_args.message_size_in_words;
3095                 counter++, message_ptr++) {
3096         get_user(message_word, message_ptr);
3097
3098         /* write data to SRAM */
3099         SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_SRAM_DATA_REG_ADDR,
3100                                                 message_word);
3101
3102         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3103                                         "SEP Driver:message_word is %lu\n",
3104                                         message_word);
3105
3106                 /* wait for write complete */
3107         SEP_WAIT_SRAM_WRITE_COMPLETE();
3108   }
3109
3110   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3111                 "SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
3112
3113   /* signal SEP */
3114   SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_HOST_SEP_GPR0_REG_ADDR,
3115                                         0x1);
3116
3117   do {
3118         SEP_READ_REGISTER(sep_dev->reg_base_address +
3119                         HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
3120   } while (!(reg_val & 0xFFFFFFFD));
3121
3122   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3123                 "SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
3124
3125   /* check the value */
3126   if (reg_val == 0x1) {
3127         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
3128                 "SEP Driver:init failed\n");
3129
3130         SEP_READ_REGISTER(sep_dev->reg_base_address + 0x8060, error);
3131         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3132                         "SEP Driver:sw monitor is %lu\n",
3133                         error);
3134
3135         /* fatal error - read erro status from GPRO */
3136         SEP_READ_REGISTER(sep_dev->reg_base_address +
3137                                 HW_HOST_SEP_HOST_GPR0_REG_ADDR,
3138                                 error);
3139         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3140                         "SEP Driver:error is %lu\n", error);
3141         goto end_function;
3142   }
3143
3144 end_function:
3145
3146   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3147                 "SEP Driver:<-------- sep_init_handler end\n");
3148
3149   return error;
3150
3151 }
3152
3153 /*
3154   this function handles the request cache and resident reallocation
3155 */
3156 static int sep_realloc_cache_resident_handler(unsigned long arg)
3157 {
3158   /* error */
3159   int                   error;
3160
3161   /* physical cache addr */
3162   unsigned long         phys_cache_address;
3163
3164   /* physical resident addr */
3165   unsigned long         phys_resident_address;
3166
3167   /* command arguments */
3168   struct sep_driver_realloc_cache_resident_t command_args;
3169
3170   /*------------------
3171         CODE
3172   ---------------------*/
3173
3174   /* copy the data */
3175   error = copy_from_user(&command_args,
3176         (void *)arg,
3177         sizeof(struct sep_driver_realloc_cache_resident_t));
3178   if (error)
3179         goto end_function;
3180
3181   /* copy cache and resident to the their intended locations */
3182   error = sep_copy_cache_resident_to_area(command_args.cache_addr,
3183                                         command_args.cache_size_in_bytes,
3184                                         command_args.resident_addr,
3185                                         command_args.resident_size_in_bytes,
3186                                         &phys_cache_address,
3187                                         &phys_resident_address);
3188   if (error)
3189         goto end_function;
3190
3191   /* lock the area (if needed) */
3192   sep_lock_cache_resident_area();
3193
3194   command_args.new_base_addr = sep_dev->phys_shared_area_addr;
3195
3196   /* find the new base address according to the lowest address between
3197         cache, resident and shared area */
3198   if (phys_resident_address < command_args.new_base_addr)
3199         command_args.new_base_addr = phys_resident_address;
3200   if (phys_cache_address < command_args.new_base_addr)
3201         command_args.new_base_addr = phys_cache_address;
3202
3203   /* set the return parameters */
3204   command_args.new_cache_addr = phys_cache_address;
3205   command_args.new_resident_addr = phys_resident_address;
3206
3207
3208   /* set the new shared area */
3209   command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
3210
3211   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3212         "SEP Driver:command_args.new_shared_area_addr is %08lx\n",
3213         command_args.new_shared_area_addr);
3214   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3215         "SEP Driver:command_args.new_base_addr is %08lx\n",
3216         command_args.new_base_addr);
3217   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3218         "SEP Driver:command_args.new_resident_addr is %08lx\n",
3219         command_args.new_resident_addr);
3220   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3221         "SEP Driver:command_args.new_cache_addr is %08lx\n",
3222         command_args.new_cache_addr);
3223
3224   /* return to user */
3225   error = copy_to_user((void *)arg,
3226         (void *)&command_args,
3227         sizeof(struct sep_driver_realloc_cache_resident_t));
3228
3229 end_function:
3230
3231   return error;
3232 }
3233
3234 /*
3235   this function handles the request for get time
3236 */
3237 static int sep_get_time_handler(unsigned long arg)
3238 {
3239   /* error */
3240   int error;
3241
3242   /* command arguments */
3243   struct sep_driver_get_time_t  command_args;
3244
3245   /*------------------------
3246         CODE
3247   --------------------------*/
3248
3249   error = sep_set_time(&command_args.time_physical_address,
3250                         &command_args.time_value);
3251
3252   /* return to user */
3253   error = copy_to_user((void *)arg,
3254         (void *)&command_args,
3255         sizeof(struct sep_driver_get_time_t));
3256
3257   return error;
3258
3259 }
3260
3261 /*
3262   This api handles the setting of API mode to blocking or non-blocking
3263 */
3264 static int sep_set_api_mode_handler(unsigned long arg)
3265 {
3266   /* error */
3267   int                   error;
3268
3269   /* flag */
3270   unsigned long mode_flag;
3271
3272   /*----------------------------
3273         CODE
3274   -----------------------------*/
3275
3276   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3277                 "SEP Driver:--------> sep_set_api_mode_handler start\n");
3278
3279   error = get_user(
3280           mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
3281   if (error)
3282         goto end_function;
3283
3284   /* set the global flag */
3285   sep_dev->block_mode_flag = mode_flag;
3286
3287
3288 end_function:
3289
3290   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3291                 "SEP Driver:<-------- sep_set_api_mode_handler end\n");
3292
3293   return error;
3294 }
3295
3296 /*
3297   This API handles the end transaction request
3298 */
3299 static int sep_end_transaction_handler(unsigned long arg)
3300 {
3301   /*----------------------------
3302         CODE
3303   -----------------------------*/
3304
3305   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3306                 "SEP Driver:--------> sep_end_transaction_handler start\n");
3307
3308 #if 0/*!SEP_DRIVER_POLLING_MODE*/
3309   /* close IMR */
3310   SEP_WRITE_REGISTER(sep_dev->reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
3311
3312   /* release IRQ line */
3313   free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
3314
3315   /* lock the sep mutex */
3316   mutex_unlock(&sep_mutex);
3317 #endif
3318
3319   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3320                 "SEP Driver:<-------- sep_end_transaction_handler end\n");
3321
3322   return 0;
3323 }
3324
3325 /* handler for flow done interrupt */
3326 static void sep_flow_done_handler(struct work_struct            *work)
3327 {
3328   /* flow context_ptr */
3329   struct sep_flow_context_t             *flow_data_ptr;
3330   /*-------------------------
3331         CODE
3332   ---------------------------*/
3333
3334   /* obtain the mutex */
3335   mutex_lock(&sep_mutex);
3336
3337   /* get the pointer to context */
3338   flow_data_ptr = (struct sep_flow_context_t *)work;
3339
3340   /* free all the current input tables in sep */
3341   sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
3342
3343   /* free all the current tables output tables in SEP (if needed) */
3344   if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
3345         sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
3346
3347   /* check if we have additional tables to be sent to SEP only input
3348         flag may be checked */
3349   if (flow_data_ptr->input_tables_flag) {
3350         /* copy the message to the shared RAM and signal SEP */
3351         memcpy((void *)flow_data_ptr->message,
3352         (void *)sep_dev->shared_area_addr,
3353         flow_data_ptr->message_size_in_bytes);
3354
3355         SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3356                         HW_HOST_HOST_SEP_GPR2_REG_ADDR,
3357                         0x2);
3358   }
3359   mutex_unlock(&sep_mutex);
3360 }
3361
3362
3363 /*
3364   This function creates a list of tables for flow and returns the data for
3365         the first and last tables of the list
3366 */
3367 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
3368                         unsigned long   first_buff_addr,
3369                         struct sep_flow_context_t       *flow_data_ptr,
3370                         struct sep_lli_entry_t          *first_table_data_ptr,
3371                         struct sep_lli_entry_t          *last_table_data_ptr,
3372                         bool                    isKernelVirtualAddress)
3373 {
3374   /* error */
3375   int                           error;
3376
3377   /* virtaul address of one buffer */
3378   unsigned long         virt_buff_addr;
3379
3380   /* virtual size of one buffer */
3381   unsigned long         virt_buff_size;
3382
3383   /* table data for each created table */
3384   struct sep_lli_entry_t        table_data;
3385
3386   /* info entry */
3387   struct sep_lli_entry_t                *info_entry_ptr;
3388
3389   /* prevouis info entry */
3390   struct sep_lli_entry_t                *prev_info_entry_ptr;
3391
3392   /* counter */
3393   unsigned long         i;
3394
3395   /*-------------------------------
3396         CODE
3397   ----------------------------------*/
3398
3399   /* init vars */
3400   error = 0;
3401   prev_info_entry_ptr = 0;
3402
3403   /* init the first table to default */
3404   table_data.physical_address = 0xffffffff;
3405   first_table_data_ptr->physical_address = 0xffffffff;
3406   table_data.block_size = 0;
3407
3408   for (i = 0; i < num_virtual_buffers; i++) {
3409         /* get the virtual buffer address */
3410         error = get_user(virt_buff_addr, &first_buff_addr);
3411         if (error)
3412         goto end_function;
3413
3414         /* get the virtual buffer size */
3415         first_buff_addr++;
3416         error = get_user(virt_buff_size, &first_buff_addr);
3417         if (error)
3418         goto end_function;
3419
3420         /* advance the address to point to the next pair of address|size */
3421         first_buff_addr++;
3422
3423         /* now prepare the one flow LLI table from the data */
3424         error = sep_prepare_one_flow_dma_table(virt_buff_addr,
3425                                         virt_buff_size,
3426                                         &table_data,
3427                                         &info_entry_ptr,
3428                                         flow_data_ptr,
3429                                         isKernelVirtualAddress);
3430         if (error)
3431         goto end_function;
3432
3433         if (i == 0) {
3434           /* if this is the first table - save it to return to the user
3435                 application */
3436           *first_table_data_ptr = table_data;
3437
3438           /* set the pointer to info entry */
3439           prev_info_entry_ptr = info_entry_ptr;
3440         } else {
3441           /* not first table - the previous table info entry should
3442                 be updated */
3443           prev_info_entry_ptr->block_size =
3444                 (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
3445                 (table_data.block_size);
3446
3447           /* set the pointer to info entry */
3448           prev_info_entry_ptr = info_entry_ptr;
3449         }
3450   }
3451
3452   /* set the last table data */
3453   *last_table_data_ptr = table_data;
3454
3455 end_function:
3456
3457   return error;
3458 }
3459
3460
3461 /*
3462   This function creates one DMA table for flow and returns its data,
3463   and pointer to its info entry
3464 */
3465 static int sep_prepare_one_flow_dma_table(
3466                         unsigned long    virt_buff_addr,
3467                         unsigned long    virt_buff_size,
3468                         struct sep_lli_entry_t          *table_data,
3469                         struct sep_lli_entry_t          **info_entry_ptr,
3470                         struct sep_flow_context_t               *flow_data_ptr,
3471                         bool                    isKernelVirtualAddress)
3472 {
3473   /* error */
3474   int                           error;
3475
3476   /* the range in pages */
3477   unsigned long         lli_array_size;
3478
3479   /* array of pointers ot page */
3480   struct sep_lli_entry_t                *lli_array;
3481
3482   /* pointer to the entry in the dma table */
3483   struct sep_lli_entry_t                *flow_dma_table_entry_ptr;
3484
3485   /* address of the dma table */
3486   unsigned long         *start_dma_table_ptr;
3487
3488   /* total table data counter */
3489   unsigned long         dma_table_data_count;
3490
3491   /* pointer that will keep the pointer t the pages of the virtual buffer */
3492   struct page           **page_array_ptr;
3493
3494   /* counter */
3495   unsigned long         entry_count;
3496
3497   /*-------------------------------
3498         CODE
3499   ----------------------------------*/
3500
3501   /* find the space for the new table */
3502   error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
3503   if (error)
3504         goto end_function;
3505
3506   /* check if the pages are in Kernel Virtual Address layout */
3507   if (isKernelVirtualAddress == true)
3508         /* lock kernel buffer in the memory */
3509         error = sep_lock_kernel_pages(virt_buff_addr,
3510                                   virt_buff_size,
3511                                   &lli_array_size,
3512                                   &lli_array,
3513                                   &page_array_ptr);
3514   else
3515         /* lock user buffer in the memory */
3516         error = sep_lock_user_pages(virt_buff_addr,
3517                                 virt_buff_size,
3518                                 &lli_array_size,
3519                                 &lli_array,
3520                                 &page_array_ptr);
3521
3522   if (error)
3523         goto end_function;
3524
3525   /* set the pointer to page array at the beginning of table - this table is
3526         now considered taken */
3527   *start_dma_table_ptr = lli_array_size;
3528
3529   /* point to the place of the pages pointers of the table */
3530   start_dma_table_ptr++;
3531
3532   /* set the pages pointer */
3533   *start_dma_table_ptr = (unsigned long)page_array_ptr;
3534
3535   /* set the pointer to the first entry */
3536   flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
3537
3538   /* now create the entries for table */
3539   for (dma_table_data_count = entry_count = 0;
3540                 entry_count <  lli_array_size;
3541                 entry_count++) {
3542         flow_dma_table_entry_ptr->physical_address =
3543                         lli_array[entry_count].physical_address;
3544
3545         flow_dma_table_entry_ptr->block_size =
3546                 lli_array[entry_count].block_size;
3547
3548         /* set the total data of a table */
3549         dma_table_data_count += lli_array[entry_count].block_size;
3550
3551         flow_dma_table_entry_ptr++;
3552   }
3553
3554   /* set the physical address */
3555   table_data->physical_address = virt_to_phys(start_dma_table_ptr);
3556
3557   /* set the num_entries and total data size */
3558   table_data->block_size = ((lli_array_size + 1) <<
3559                         SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
3560                         (dma_table_data_count);
3561
3562   /* set the info entry */
3563   flow_dma_table_entry_ptr->physical_address = 0xffffffff;
3564   flow_dma_table_entry_ptr->block_size = 0;
3565
3566   /* set the pointer to info entry */
3567   *info_entry_ptr = flow_dma_table_entry_ptr;
3568
3569   /* the array of the lli entries */
3570   kfree(lli_array);
3571
3572 end_function:
3573
3574   return error;
3575 }
3576
3577
3578 /*
3579   This function returns pointer to the  flow data structure
3580   that conatins the given id
3581 */
3582 static int sep_find_flow_context(
3583                                 unsigned long   flow_id,
3584                                 struct sep_flow_context_t **flow_data_ptr)
3585 {
3586   /* count */
3587   unsigned long count;
3588
3589   /* error */
3590   int                   error;
3591
3592   /*-----------------------
3593         CODE
3594   ---------------------------*/
3595
3596   error = 0;
3597
3598   /*
3599          always search for flow with id default first - in case we
3600          already started working on the flow there can be no situation
3601          when 2 flows are with default flag
3602   */
3603   for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
3604         if (sep_dev->flows_data_array[count].flow_id == flow_id) {
3605           *flow_data_ptr = &sep_dev->flows_data_array[count];
3606           break;
3607         }
3608   }
3609
3610   if (count == SEP_DRIVER_NUM_FLOWS)
3611         /* no flow found  */
3612         error = -ENOMEM;
3613
3614   return error;
3615 }
3616
3617 /*
3618   this function find a space for the new flow dma table
3619 */
3620 static int sep_find_free_flow_dma_table_space(
3621                         unsigned long   **table_address_ptr)
3622 {
3623   /* error */
3624   int                   error;
3625
3626   /* pointer to the id field of the flow dma table */
3627   unsigned long         *start_table_ptr;
3628
3629   /* start address of the flow dma area */
3630   unsigned long flow_dma_area_start_addr;
3631
3632   /* end address of the flow dma area */
3633   unsigned long flow_dma_area_end_addr;
3634
3635   /* maximum table size in words */
3636   unsigned long table_size_in_words;
3637
3638   /*---------------------
3639         CODE
3640   -----------------------*/
3641
3642   error = 0;
3643
3644   /* find the start address of the flow DMA table area */
3645   flow_dma_area_start_addr = sep_dev->shared_area_addr +
3646                         SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
3647
3648   /* set end address of the flow table area */
3649   flow_dma_area_end_addr = flow_dma_area_start_addr +
3650                         SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
3651
3652   /* set table size in words */
3653   table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
3654                         (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
3655
3656   /* set the pointer to the start address of DMA area */
3657   start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
3658
3659   /* find the space for the next table */
3660   while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
3661                         ((unsigned long)start_table_ptr <
3662                         flow_dma_area_end_addr))
3663         start_table_ptr += table_size_in_words;
3664
3665   /* check if we reached the end of floa tables area */
3666   if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
3667         error = -1;
3668   else
3669         *table_address_ptr = start_table_ptr;
3670
3671   return error;
3672 }
3673
3674 /*
3675   this function goes over all the flow tables connected to the given
3676         table and deallocate them
3677 */
3678 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
3679 {
3680   /* id poiner */
3681   unsigned long         *table_ptr;
3682
3683   /* end address of the flow dma area */
3684   unsigned long num_entries;
3685
3686   unsigned long num_pages;
3687
3688   /* pages ptr */
3689   struct page           **pages_ptr;
3690
3691   /* maximum table size in words */
3692   struct sep_lli_entry_t                *info_entry_ptr;
3693
3694   /*-------------------------------
3695         CODE
3696   ---------------------------------*/
3697
3698   /* set the pointer to the first table */
3699   table_ptr = (unsigned long *)first_table_ptr->physical_address;
3700
3701   /* set the num of entries */
3702   num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
3703                                 & SEP_NUM_ENTRIES_MASK;
3704
3705   /* go over all the connected tables */
3706   while (*table_ptr != 0xffffffff) {
3707         /* get number of pages */
3708         num_pages = *(table_ptr - 2);
3709
3710         /* get the pointer to the pages */
3711         pages_ptr = (struct page **)(*(table_ptr - 1));
3712
3713         /* free the pages */
3714         sep_free_dma_pages(pages_ptr, num_pages, 1);
3715
3716         /* goto to the info entry */
3717         info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
3718                                         (num_entries - 1);
3719
3720         table_ptr = (unsigned long *)info_entry_ptr->physical_address;
3721         num_entries = (info_entry_ptr->block_size >>
3722                 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
3723   }
3724
3725   return;
3726 }
3727
3728 /*
3729   This function handler the set flow id command
3730 */
3731 static int sep_set_flow_id_handler(unsigned long arg)
3732 {
3733   /* error */
3734   int                                   error;
3735
3736   /* flow _id */
3737   unsigned long          flow_id;
3738
3739   /* pointer to flow data structre */
3740   struct sep_flow_context_t             *flow_data_ptr;
3741
3742   /*----------------------
3743         CODE
3744   -----------------------*/
3745
3746   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3747                 "------------>SEP Driver: sep_set_flow_id_handler start\n");
3748
3749   error = get_user(flow_id,
3750         &(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
3751   if (error)
3752         goto end_function;
3753
3754   /* find the flow data structure that was just used for creating new flow
3755         - its id should be default */
3756   error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
3757   if (error)
3758         goto end_function;
3759
3760   /* set flow id */
3761   flow_data_ptr->flow_id = flow_id;
3762
3763 end_function:
3764
3765   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3766                 "SEP Driver:<-------- sep_set_flow_id_handler end\n");
3767
3768
3769   return error;
3770 }
3771
3772
3773 /*
3774   calculates time and sets it at the predefined address
3775 */
3776 static int sep_set_time(unsigned long           *address_ptr,
3777                         unsigned long           *time_in_sec_ptr)
3778 {
3779   /*  time struct */
3780   struct timeval  time;
3781
3782   /* address of time in the kernel */
3783   unsigned long time_addr;
3784
3785
3786   /*------------------------
3787         CODE
3788   --------------------------*/
3789
3790   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3791                 "SEP Driver:--------> sep_set_time start\n");
3792
3793
3794   do_gettimeofday(&time);
3795
3796   /* set value in the SYSTEM MEMORY offset */
3797   time_addr = sep_dev->message_shared_area_addr +
3798                         SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
3799
3800   *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
3801   *(unsigned long *)(time_addr + 4) = time.tv_sec;
3802
3803   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3804                         "SEP Driver:time.tv_sec is %lu\n",
3805                         time.tv_sec);
3806   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3807                         "SEP Driver:time_addr is %lu\n",
3808                         time_addr);
3809   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3810                         "SEP Driver:g_message_shared_area_addr is %lu\n",
3811                         sep_dev->message_shared_area_addr);
3812
3813   /* set the output parameters if needed */
3814   if (address_ptr)
3815         *address_ptr = sep_shared_area_virt_to_phys(time_addr);
3816
3817   if (time_in_sec_ptr)
3818         *time_in_sec_ptr = time.tv_sec;
3819
3820   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3821                 "SEP Driver:<-------- sep_set_time end\n");
3822
3823   return 0;
3824 }
3825
3826 /*
3827   PATCH for configuring the DMA to single burst instead of multi-burst
3828 */
3829 static void sep_configure_dma_burst(void)
3830 {
3831
3832 #define          HW_AHB_RD_WR_BURSTS_REG_ADDR            0x0E10UL
3833
3834   unsigned long regVal;
3835
3836   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3837                 "SEP Driver:<-------- sep_configure_dma_burst start \n");
3838
3839   /* request access to registers from SEP */
3840   SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3841                                         HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2UL);
3842
3843   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3844                 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
3845
3846   SEP_READ_REGISTER(sep_dev->reg_base_address +
3847                                         HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3848   while (regVal)
3849         SEP_READ_REGISTER(sep_dev->reg_base_address +
3850                                         HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3851
3852   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3853                 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
3854
3855   /* set the DMA burst register to single burst*/
3856   SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3857                                         HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
3858
3859   /* release the sep busy */
3860   SEP_WRITE_REGISTER(sep_dev->reg_base_address +
3861                                         HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
3862   SEP_READ_REGISTER(sep_dev->reg_base_address +
3863                                         HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3864   while (regVal != 0x0)
3865         SEP_READ_REGISTER(sep_dev->reg_base_address +
3866                                         HW_HOST_SEP_BUSY_REG_ADDR, regVal);
3867
3868   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3869                 "SEP Driver:<-------- sep_configure_dma_burst done  \n");
3870
3871 }
3872
3873 module_init(sep_init);
3874 module_exit(sep_exit);
3875
3876 MODULE_LICENSE("GPL");