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