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