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