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