3 * sep_main_mod.c - Security Processor Driver main group of functions
5 * Copyright(c) 2009 Intel Corporation. All rights reserved.
6 * Copyright(c) 2009 Discretix. All rights reserved.
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)
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
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.
24 * Mark Allyn mark.a.allyn@intel.com
28 * 2009.06.26 Initial publish
32 #include <linux/init.h>
33 #include <linux/module.h>
35 #include <linux/cdev.h>
36 #include <linux/kdev_t.h>
37 #include <linux/mutex.h>
39 #include <linux/poll.h>
40 #include <linux/wait.h>
41 #include <linux/pci.h>
42 #include <linux/firmware.h>
43 #include <asm/ioctl.h>
44 #include <linux/ioport.h>
46 #include <linux/interrupt.h>
47 #include <linux/pagemap.h>
48 #include <asm/cacheflush.h>
49 #include "sep_driver_hw_defs.h"
50 #include "sep_driver_config.h"
51 #include "sep_driver_api.h"
52 #include "sep_driver_ext_api.h"
55 #if SEP_DRIVER_ARM_DEBUG_MODE
57 #define CRYS_SEP_ROM_length 0x4000
58 #define CRYS_SEP_ROM_start_address 0x8000C000UL
59 #define CRYS_SEP_ROM_start_address_offset 0xC000UL
60 #define SEP_ROM_BANK_register 0x80008420UL
61 #define SEP_ROM_BANK_register_offset 0x8420UL
62 #define SEP_RAR_IO_MEM_REGION_START_ADDRESS 0x82000000
65 * THESE 2 definitions are specific to the board - must be
66 * defined during integration
68 #define SEP_RAR_IO_MEM_REGION_START_ADDRESS 0xFF0D0000
72 static void sep_load_rom_code(void)
75 unsigned long i, k, j;
78 unsigned long warning;
80 /* Loading ROM from SEP_ROM_image.h file */
81 k = sizeof(CRYS_SEP_ROM);
83 edbg("SEP Driver: DX_CC_TST_SepRomLoader start\n");
85 edbg("SEP Driver: k is %lu\n", k);
86 edbg("SEP Driver: sep_dev->reg_base_address is %p\n", sep_dev->reg_base_address);
87 edbg("SEP Driver: CRYS_SEP_ROM_start_address_offset is %p\n", CRYS_SEP_ROM_start_address_offset);
89 for (i = 0; i < 4; i++) {
91 sep_write_reg(sep_dev, SEP_ROM_BANK_register_offset, i);
93 for (j = 0; j < CRYS_SEP_ROM_length / 4; j++) {
94 sep_write_reg(sep_dev, CRYS_SEP_ROM_start_address_offset + 4 * j, CRYS_SEP_ROM[i * 0x1000 + j]);
99 j = CRYS_SEP_ROM_length;
106 sep_write_reg(sep_dev, HW_HOST_SEP_SW_RST_REG_ADDR, 0x1);
108 /* poll for SEP ROM boot finish */
110 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
113 edbg("SEP Driver: ROM polling ended\n");
117 /* fatal error - read erro status from GPRO */
118 Error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
119 edbg("SEP Driver: ROM polling case 1\n");
122 /* Boot First Phase ended */
123 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
124 edbg("SEP Driver: ROM polling case 2\n");
127 /* Cold boot ended successfully */
128 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
129 edbg("SEP Driver: ROM polling case 4\n");
133 /* Warmboot ended successfully */
134 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
135 edbg("SEP Driver: ROM polling case 8\n");
139 /* ColdWarm boot ended successfully */
140 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
141 edbg("SEP Driver: ROM polling case 16\n");
145 edbg("SEP Driver: ROM polling case 32\n");
152 static void sep_load_rom_code(void) { }
153 #endif /* SEP_DRIVER_ARM_DEBUG_MODE */
157 /*----------------------------------------
159 -----------------------------------------*/
161 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
162 #define BASE_ADDRESS_FOR_SYSTEM 0xfffc0000
163 #define SEP_RAR_IO_MEM_REGION_SIZE 0x40000
165 /*--------------------------------------------
167 --------------------------------------------*/
169 /* debug messages level */
170 INT_MODULE_PARM(sepDebug, 0x0);
171 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
173 /* Keep this a single static object for now to keep the conversion easy */
175 static struct sep_device sep_instance;
176 static struct sep_device *sep_dev = &sep_instance;
179 mutex for the access to the internals of the sep driver
181 static DEFINE_MUTEX(sep_mutex);
184 /* wait queue head (event) of the driver */
185 static DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
188 This functions copies the cache and resident from their source location into
189 destination memory, which is external to Linux VM and is given as
192 static int sep_copy_cache_resident_to_area(unsigned long src_cache_addr, unsigned long cache_size_in_bytes, unsigned long src_resident_addr, unsigned long resident_size_in_bytes, unsigned long *dst_new_cache_addr_ptr, unsigned long *dst_new_resident_addr_ptr)
194 unsigned long resident_addr;
195 unsigned long cache_addr;
196 const struct firmware *fw;
198 char *cache_name = "cache.image.bin";
199 char *res_name = "resident.image.bin";
204 /*--------------------------------
206 -------------------------------------*/
209 edbg("SEP Driver:rar_virtual is %p\n", sep_dev->rar_virtual_address);
210 edbg("SEP Driver:rar_physical is %08lx\n", sep_dev->rar_physical_address);
212 sep_dev->rar_region_addr = (unsigned long) sep_dev->rar_virtual_address;
214 sep_dev->cache_physical_address = sep_dev->rar_physical_address;
215 sep_dev->cache_virtual_address = sep_dev->rar_virtual_address;
218 error = request_firmware(&fw, cache_name, &sep_dev->sep_pci_dev_ptr->dev);
220 edbg("SEP Driver:cant request cache fw\n");
224 edbg("SEP Driver:cache data loc is %p\n", (void *) fw->data);
225 edbg("SEP Driver:cache data size is %08Zx\n", fw->size);
227 memcpy((void *) sep_dev->cache_virtual_address, (void *) fw->data, fw->size);
229 sep_dev->cache_size = fw->size;
231 cache_addr = (unsigned long) sep_dev->cache_virtual_address;
233 release_firmware(fw);
235 sep_dev->resident_physical_address = sep_dev->cache_physical_address + sep_dev->cache_size;
236 sep_dev->resident_virtual_address = sep_dev->cache_virtual_address + sep_dev->cache_size;
239 error = request_firmware(&fw, res_name, &sep_dev->sep_pci_dev_ptr->dev);
241 edbg("SEP Driver:cant request res fw\n");
245 edbg("SEP Driver:res data loc is %p\n", (void *) fw->data);
246 edbg("SEP Driver:res data size is %08Zx\n", fw->size);
248 memcpy((void *) sep_dev->resident_virtual_address, (void *) fw->data, fw->size);
250 sep_dev->resident_size = fw->size;
252 release_firmware(fw);
254 resident_addr = (unsigned long) sep_dev->resident_virtual_address;
256 edbg("SEP Driver:resident_addr (physical )is %08lx\n", sep_dev->resident_physical_address);
257 edbg("SEP Driver:cache_addr (physical) is %08lx\n", sep_dev->cache_physical_address);
259 edbg("SEP Driver:resident_addr (logical )is %08lx\n", resident_addr);
260 edbg("SEP Driver:cache_addr (logical) is %08lx\n", cache_addr);
262 edbg("SEP Driver:resident_size is %08lx\n", sep_dev->resident_size);
263 edbg("SEP Driver:cache_size is %08lx\n", sep_dev->cache_size);
267 /* physical addresses */
268 *dst_new_cache_addr_ptr = sep_dev->cache_physical_address;
269 *dst_new_resident_addr_ptr = sep_dev->resident_physical_address;
275 This functions maps and allocates the
276 shared area on the external RAM (device)
277 The input is shared_area_size - the size of the memory to
278 allocate. The outputs
279 are kernel_shared_area_addr_ptr - the kerenl
280 address of the mapped and allocated
281 shared area, and phys_shared_area_addr_ptr
282 - the physical address of the shared area
284 static int sep_map_and_alloc_shared_area(unsigned long shared_area_size, unsigned long *kernel_shared_area_addr_ptr, unsigned long *phys_shared_area_addr_ptr)
286 // shared_virtual_address = ioremap_nocache(0xda00000,shared_area_size);
287 sep_dev->shared_virtual_address = kmalloc(shared_area_size, GFP_KERNEL);
288 if (!sep_dev->shared_virtual_address) {
289 edbg("sep_driver:shared memory kmalloc failed\n");
293 sep_dev->shared_physical_address = __pa(sep_dev->shared_virtual_address);
294 /* shared_physical_address = 0xda00000; */
295 *kernel_shared_area_addr_ptr = (unsigned long) sep_dev->shared_virtual_address;
296 /* set the physical address of the shared area */
297 *phys_shared_area_addr_ptr = sep_dev->shared_physical_address;
298 edbg("SEP Driver:shared_virtual_address is %p\n", sep_dev->shared_virtual_address);
299 edbg("SEP Driver:shared_region_size is %08lx\n", shared_area_size);
300 edbg("SEP Driver:shared_physical_addr is %08lx\n", *phys_shared_area_addr_ptr);
306 This functions unmaps and deallocates the shared area
307 on the external RAM (device)
308 The input is shared_area_size - the size of the memory to deallocate,kernel_
309 shared_area_addr_ptr - the kernel address of the mapped and allocated
310 shared area,phys_shared_area_addr_ptr - the physical address of
313 static void sep_unmap_and_free_shared_area(unsigned long shared_area_size, unsigned long kernel_shared_area_addr, unsigned long phys_shared_area_addr)
315 kfree((void *) kernel_shared_area_addr);
319 This functions returns the physical address inside shared area according
320 to the virtual address. It can be either on the externa RAM device
321 (ioremapped), or on the system RAM
322 This implementation is for the external RAM
324 static unsigned long sep_shared_area_virt_to_phys(unsigned long virt_address)
326 edbg("SEP Driver:sh virt to phys v %08lx\n", virt_address);
327 edbg("SEP Driver:sh virt to phys p %08lx\n", sep_dev->shared_physical_address + (virt_address - (unsigned long) sep_dev->shared_virtual_address));
329 return (unsigned long) sep_dev->shared_physical_address + (virt_address - (unsigned long) sep_dev->shared_virtual_address);
333 This functions returns the virtual address inside shared area
334 according to the physical address. It can be either on the
335 externa RAM device (ioremapped), or on the system RAM This implementation
336 is for the external RAM
338 static unsigned long sep_shared_area_phys_to_virt(unsigned long phys_address)
340 return (unsigned long) sep_dev->shared_virtual_address + (phys_address - sep_dev->shared_physical_address);
344 /*----------------------------------------------------------------------
345 open function of the character driver - must only lock the mutex
346 must also release the memory data pool allocations
347 ------------------------------------------------------------------------*/
348 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
352 dbg("SEP Driver:--------> open start\n");
356 /* check the blocking mode */
357 if (sep_dev->block_mode_flag)
359 mutex_lock(&sep_mutex);
361 error = mutex_trylock(&sep_mutex);
363 /* check the error */
365 edbg("SEP Driver: down_interruptible failed\n");
370 /* release data pool allocations */
371 sep_dev->data_pool_bytes_allocated = 0;
374 dbg("SEP Driver:<-------- open end\n");
381 /*------------------------------------------------------------
383 -------------------------------------------------------------*/
384 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
386 dbg("----------->SEP Driver: sep_release start\n");
388 #if 0 /*!SEP_DRIVER_POLLING_MODE */
390 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
392 /* release IRQ line */
393 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
397 /* unlock the sep mutex */
398 mutex_unlock(&sep_mutex);
400 dbg("SEP Driver:<-------- sep_release end\n");
408 /*---------------------------------------------------------------
409 map function - this functions maps the message shared area
410 -----------------------------------------------------------------*/
411 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
413 unsigned long phys_addr;
415 dbg("-------->SEP Driver: mmap start\n");
417 /* check that the size of the mapped range is as the size of the message
419 if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
420 edbg("SEP Driver mmap requested size is more than allowed\n");
421 printk(KERN_WARNING "SEP Driver mmap requested size is more \
423 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
424 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
428 edbg("SEP Driver:g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
430 /* get physical address */
431 phys_addr = sep_dev->phys_shared_area_addr;
433 edbg("SEP Driver: phys_addr is %08lx\n", phys_addr);
435 if (remap_pfn_range(vma, vma->vm_start, phys_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
436 edbg("SEP Driver remap_page_range failed\n");
437 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
441 dbg("SEP Driver:<-------- mmap end\n");
447 /*-----------------------------------------------
449 *----------------------------------------------*/
450 static unsigned int sep_poll(struct file *filp, poll_table * wait)
453 unsigned int mask = 0;
454 unsigned long retVal = 0; /* flow id */
456 dbg("---------->SEP Driver poll: start\n");
459 #if SEP_DRIVER_POLLING_MODE
461 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
462 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
464 for (count = 0; count < 10 * 4; count += 4)
465 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)));
468 sep_dev->sep_to_host_reply_counter++;
470 /* add the event to the polling wait table */
471 poll_wait(filp, &g_sep_event, wait);
475 edbg("sep_dev->host_to_sep_send_counter is %lu\n", sep_dev->host_to_sep_send_counter);
476 edbg("sep_dev->sep_to_host_reply_counter is %lu\n", sep_dev->sep_to_host_reply_counter);
478 /* check if the data is ready */
479 if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
480 for (count = 0; count < 12 * 4; count += 4)
481 edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
483 for (count = 0; count < 10 * 4; count += 4)
484 edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + 0x1800 + count)));
486 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
487 edbg("retVal is %lu\n", retVal);
488 /* check if the this is sep reply or request */
490 edbg("SEP Driver: sep request in\n");
492 mask |= POLLOUT | POLLWRNORM;
494 edbg("SEP Driver: sep reply in\n");
495 mask |= POLLIN | POLLRDNORM;
498 dbg("SEP Driver:<-------- poll exit\n");
503 calculates time and sets it at the predefined address
505 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr)
508 /* address of time in the kernel */
509 unsigned long time_addr;
512 dbg("SEP Driver:--------> sep_set_time start\n");
514 do_gettimeofday(&time);
516 /* set value in the SYSTEM MEMORY offset */
517 time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
519 *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN;
520 *(unsigned long *) (time_addr + 4) = time.tv_sec;
522 edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec);
523 edbg("SEP Driver:time_addr is %lu\n", time_addr);
524 edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr);
526 /* set the output parameters if needed */
528 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
531 *time_in_sec_ptr = time.tv_sec;
533 dbg("SEP Driver:<-------- sep_set_time end\n");
539 This function raises interrupt to SEP that signals that is has a new
542 static void sep_send_command_handler(void)
546 dbg("SEP Driver:--------> sep_send_command_handler start\n");
552 for (count = 0; count < 12 * 4; count += 4)
553 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
556 sep_dev->host_to_sep_send_counter++;
557 /* send interrupt to SEP */
558 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
559 dbg("SEP Driver:<-------- sep_send_command_handler end\n");
564 This function raises interrupt to SEPm that signals that is has a
565 new command from HOST
567 static void sep_send_reply_command_handler(void)
571 dbg("SEP Driver:--------> sep_send_reply_command_handler start\n");
575 for (count = 0; count < 12 * 4; count += 4)
576 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
578 sep_dev->host_to_sep_send_counter++;
579 /* send the interrupt to SEP */
580 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep_dev->host_to_sep_send_counter);
581 /* update both counters */
582 sep_dev->host_to_sep_send_counter++;
583 sep_dev->sep_to_host_reply_counter++;
584 dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n");
588 This function handles the allocate data pool memory request
589 This function returns calculates the physical address of the
590 allocated memory, and the offset of this area from the mapped address.
591 Therefore, the FVOs in user space can calculate the exact virtual
592 address of this allocated memory
594 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
597 struct sep_driver_alloc_t command_args;
599 dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
601 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
605 /* allocate memory */
606 if ((sep_dev->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
611 /* set the virtual and physical address */
612 command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
613 command_args.phys_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
615 /* write the memory back to the user space */
616 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
620 /* set the allocation */
621 sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
624 dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
629 This function handles write into allocated data pool command
631 static int sep_write_into_data_pool_handler(unsigned long arg)
634 unsigned long virt_address;
635 unsigned long app_in_address;
636 unsigned long num_bytes;
637 unsigned long data_pool_area_addr;
639 dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n");
641 /* get the application address */
642 error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address));
646 /* get the virtual kernel address address */
647 error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
651 /* get the number of bytes */
652 error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
656 /* calculate the start of the data pool */
657 data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
660 /* check that the range of the virtual kernel address is correct */
661 if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
665 /* copy the application data */
666 error = copy_from_user((void *) virt_address, (void *) app_in_address, num_bytes);
668 dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
673 this function handles the read from data pool command
675 static int sep_read_from_data_pool_handler(unsigned long arg)
678 /* virtual address of dest application buffer */
679 unsigned long app_out_address;
680 /* virtual address of the data pool */
681 unsigned long virt_address;
682 unsigned long num_bytes;
683 unsigned long data_pool_area_addr;
685 dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n");
687 /* get the application address */
688 error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address));
692 /* get the virtual kernel address address */
693 error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
697 /* get the number of bytes */
698 error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
702 /* calculate the start of the data pool */
703 data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
705 /* check that the range of the virtual kernel address is correct */
706 if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
711 /* copy the application data */
712 error = copy_to_user((void *) app_out_address, (void *) virt_address, num_bytes);
714 dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
719 This function releases all the application virtual buffer physical pages,
720 that were previously locked
722 static int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag)
727 for (count = 0; count < num_pages; count++) {
728 /* the out array was written, therefore the data was changed */
729 if (!PageReserved(page_array_ptr[count]))
730 SetPageDirty(page_array_ptr[count]);
731 page_cache_release(page_array_ptr[count]);
734 /* free in pages - the data was only read, therefore no update was done
736 for (count = 0; count < num_pages; count++)
737 page_cache_release(page_array_ptr[count]);
742 kfree(page_array_ptr);
748 This function locks all the physical pages of the kernel virtual buffer
749 and construct a basic lli array, where each entry holds the physical
750 page address and the size that application data holds in this physical pages
752 static 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)
755 /* the the page of the end address of the user space buffer */
756 unsigned long end_page;
757 /* the page of the start address of the user space buffer */
758 unsigned long start_page;
759 /* the range in pages */
760 unsigned long num_pages;
761 struct sep_lli_entry_t *lli_array;
762 /* next kernel address to map */
763 unsigned long next_kernel_address;
766 dbg("SEP Driver:--------> sep_lock_kernel_pages start\n");
768 /* set start and end pages and num pages */
769 end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
770 start_page = kernel_virt_addr >> PAGE_SHIFT;
771 num_pages = end_page - start_page + 1;
773 edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr);
774 edbg("SEP Driver: data_size is %lu\n", data_size);
775 edbg("SEP Driver: start_page is %lx\n", start_page);
776 edbg("SEP Driver: end_page is %lx\n", end_page);
777 edbg("SEP Driver: num_pages is %lu\n", num_pages);
779 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
781 edbg("SEP Driver: kmalloc for lli_array failed\n");
786 /* set the start address of the first page - app data may start not at
787 the beginning of the page */
788 lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr);
790 /* check that not all the data is in the first page only */
791 if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
792 lli_array[0].block_size = data_size;
794 lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
797 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);
799 /* advance the address to the start of the next page */
800 next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
802 /* go from the second page to the prev before last */
803 for (count = 1; count < (num_pages - 1); count++) {
804 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
805 lli_array[count].block_size = PAGE_SIZE;
807 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);
808 next_kernel_address += PAGE_SIZE;
811 /* if more then 1 pages locked - then update for the last page size needed */
813 /* update the address of the last page */
814 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
816 /* set the size of the last page */
817 lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK);
819 if (lli_array[count].block_size == 0) {
820 dbg("app_virt_addr is %08lx\n", kernel_virt_addr);
821 dbg("data_size is %lu\n", data_size);
825 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);
827 /* set output params */
828 *lli_array_ptr = lli_array;
829 *num_pages_ptr = num_pages;
832 dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n");
837 This function locks all the physical pages of the application virtual buffer
838 and construct a basic lli array, where each entry holds the physical page
839 address and the size that application data holds in this physical pages
841 static 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)
844 /* the the page of the end address of the user space buffer */
845 unsigned long end_page;
846 /* the page of the start address of the user space buffer */
847 unsigned long start_page;
848 /* the range in pages */
849 unsigned long num_pages;
850 struct page **page_array;
851 struct sep_lli_entry_t *lli_array;
855 dbg("SEP Driver:--------> sep_lock_user_pages start\n");
857 /* set start and end pages and num pages */
858 end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
859 start_page = app_virt_addr >> PAGE_SHIFT;
860 num_pages = end_page - start_page + 1;
862 edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr);
863 edbg("SEP Driver: data_size is %lu\n", data_size);
864 edbg("SEP Driver: start_page is %lu\n", start_page);
865 edbg("SEP Driver: end_page is %lu\n", end_page);
866 edbg("SEP Driver: num_pages is %lu\n", num_pages);
868 /* allocate array of pages structure pointers */
869 page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
871 edbg("SEP Driver: kmalloc for page_array failed\n");
877 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
879 edbg("SEP Driver: kmalloc for lli_array failed\n");
882 goto end_function_with_error1;
885 /* convert the application virtual address into a set of physical */
886 down_read(¤t->mm->mmap_sem);
887 result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0);
888 up_read(¤t->mm->mmap_sem);
890 /* check the number of pages locked - if not all then exit with error */
891 if (result != num_pages) {
892 dbg("SEP Driver: not all pages locked by get_user_pages\n");
895 goto end_function_with_error2;
898 /* flush the cache */
899 for (count = 0; count < num_pages; count++)
900 flush_dcache_page(page_array[count]);
902 /* set the start address of the first page - app data may start not at
903 the beginning of the page */
904 lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK));
906 /* check that not all the data is in the first page only */
907 if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
908 lli_array[0].block_size = data_size;
910 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
913 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);
915 /* go from the second page to the prev before last */
916 for (count = 1; count < (num_pages - 1); count++) {
917 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
918 lli_array[count].block_size = PAGE_SIZE;
920 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);
923 /* if more then 1 pages locked - then update for the last page size needed */
925 /* update the address of the last page */
926 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
928 /* set the size of the last page */
929 lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK);
931 if (lli_array[count].block_size == 0) {
932 dbg("app_virt_addr is %08lx\n", app_virt_addr);
933 dbg("data_size is %lu\n", data_size);
936 edbg("lli_array[%lu].physical_address is %08lx, \
937 lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
940 /* set output params */
941 *lli_array_ptr = lli_array;
942 *num_pages_ptr = num_pages;
943 *page_array_ptr = page_array;
946 end_function_with_error2:
947 /* release the cache */
948 for (count = 0; count < num_pages; count++)
949 page_cache_release(page_array[count]);
951 end_function_with_error1:
954 dbg("SEP Driver:<-------- sep_lock_user_pages end\n");
960 this function calculates the size of data that can be inserted into the lli
961 table from this array the condition is that either the table is full
962 (all etnries are entered), or there are no more entries in the lli array
964 static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries)
966 unsigned long table_data_size = 0;
967 unsigned long counter;
969 /* calculate the data in the out lli table if till we fill the whole
970 table or till the data has ended */
971 for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++)
972 table_data_size += lli_in_array_ptr[counter].block_size;
973 return table_data_size;
977 this functions builds ont lli table from the lli_array according to
978 the given size of data
980 static 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)
982 unsigned long curr_table_data_size;
983 /* counter of lli array entry */
984 unsigned long array_counter;
986 dbg("SEP Driver:--------> sep_build_lli_table start\n");
988 /* init currrent table data size and lli array entry counter */
989 curr_table_data_size = 0;
991 *num_table_entries_ptr = 1;
993 edbg("SEP Driver:table_data_size is %lu\n", table_data_size);
995 /* fill the table till table size reaches the needed amount */
996 while (curr_table_data_size < table_data_size) {
997 /* update the number of entries in table */
998 (*num_table_entries_ptr)++;
1000 lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address;
1001 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1002 curr_table_data_size += lli_table_ptr->block_size;
1004 edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1005 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1006 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1008 /* check for overflow of the table data */
1009 if (curr_table_data_size > table_data_size) {
1010 edbg("SEP Driver:curr_table_data_size > table_data_size\n");
1012 /* update the size of block in the table */
1013 lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1015 /* update the physical address in the lli array */
1016 lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size;
1018 /* update the block size left in the lli array */
1019 lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size);
1021 /* advance to the next entry in the lli_array */
1024 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1025 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1027 /* move to the next entry in table */
1031 /* set the info entry to default */
1032 lli_table_ptr->physical_address = 0xffffffff;
1033 lli_table_ptr->block_size = 0;
1035 edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1036 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1037 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1039 /* set the output parameter */
1040 *num_processed_entries_ptr += array_counter;
1042 edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr);
1043 dbg("SEP Driver:<-------- sep_build_lli_table end\n");
1048 this function goes over the list of the print created tables and
1051 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size)
1053 unsigned long table_count;
1054 unsigned long entries_count;
1056 dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
1059 while ((unsigned long) lli_table_ptr != 0xffffffff) {
1060 edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size);
1061 edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries);
1063 /* print entries of the table (without info entry) */
1064 for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) {
1065 edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr);
1066 edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size);
1069 /* point to the info entry */
1072 edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1073 edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1076 table_data_size = lli_table_ptr->block_size & 0xffffff;
1077 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1078 lli_table_ptr = (struct sep_lli_entry_t *)
1079 (lli_table_ptr->physical_address);
1081 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);
1083 if ((unsigned long) lli_table_ptr != 0xffffffff)
1084 lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_area_phys_to_virt((unsigned long) lli_table_ptr);
1088 dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1093 This function prepares only input DMA table for synhronic symmetric
1096 static int sep_prepare_input_dma_table(unsigned long app_virt_addr, unsigned long data_size, unsigned long block_size, unsigned long *lli_table_ptr, unsigned long *num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress)
1098 /* pointer to the info entry of the table - the last entry */
1099 struct sep_lli_entry_t *info_entry_ptr;
1100 /* array of pointers ot page */
1101 struct sep_lli_entry_t *lli_array_ptr;
1102 /* points to the first entry to be processed in the lli_in_array */
1103 unsigned long current_entry;
1104 /* num entries in the virtual buffer */
1105 unsigned long sep_lli_entries;
1106 /* lli table pointer */
1107 struct sep_lli_entry_t *in_lli_table_ptr;
1108 /* the total data in one table */
1109 unsigned long table_data_size;
1110 /* number of entries in lli table */
1111 unsigned long num_entries_in_table;
1112 /* next table address */
1113 unsigned long lli_table_alloc_addr;
1114 unsigned long result;
1116 dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
1118 edbg("SEP Driver:data_size is %lu\n", data_size);
1119 edbg("SEP Driver:block_size is %lu\n", block_size);
1121 /* initialize the pages pointers */
1122 sep_dev->in_page_array = 0;
1123 sep_dev->in_num_pages = 0;
1125 if (data_size == 0) {
1126 /* special case - created 2 entries table with zero data */
1127 in_lli_table_ptr = (struct sep_lli_entry_t *) (sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1128 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1129 in_lli_table_ptr->block_size = 0;
1132 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1133 in_lli_table_ptr->block_size = 0;
1135 *lli_table_ptr = sep_dev->phys_shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1136 *num_entries_ptr = 2;
1137 *table_data_size_ptr = 0;
1142 /* check if the pages are in Kernel Virtual Address layout */
1143 if (isKernelVirtualAddress == true)
1144 /* lock the pages of the kernel buffer and translate them to pages */
1145 result = sep_lock_kernel_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
1147 /* lock the pages of the user buffer and translate them to pages */
1148 result = sep_lock_user_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
1153 edbg("SEP Driver:output sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1157 sep_lli_entries = sep_dev->in_num_pages;
1159 /* initiate to point after the message area */
1160 lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1162 /* loop till all the entries in in array are not processed */
1163 while (current_entry < sep_lli_entries) {
1164 /* set the new input and output tables */
1165 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
1167 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1169 /* calculate the maximum size of data for input table */
1170 table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry));
1172 /* now calculate the table size so that it will be module block size */
1173 table_data_size = (table_data_size / block_size) * block_size;
1175 edbg("SEP Driver:output table_data_size is %lu\n", table_data_size);
1177 /* construct input lli table */
1178 sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, ¤t_entry, &num_entries_in_table, table_data_size);
1180 if (info_entry_ptr == 0) {
1181 /* set the output parameters to physical addresses */
1182 *lli_table_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
1183 *num_entries_ptr = num_entries_in_table;
1184 *table_data_size_ptr = table_data_size;
1186 edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr);
1188 /* update the info entry of the previous in table */
1189 info_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
1190 info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
1193 /* save the pointer to the info entry of the current tables */
1194 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1197 /* print input tables */
1198 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1199 sep_shared_area_phys_to_virt(*lli_table_ptr), *num_entries_ptr, *table_data_size_ptr);
1201 /* the array of the pages */
1202 kfree(lli_array_ptr);
1204 dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1210 This function creates the input and output dma tables for
1211 symmetric operations (AES/DES) according to the block size from LLI arays
1213 static int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
1214 unsigned long sep_in_lli_entries,
1215 struct sep_lli_entry_t *lli_out_array,
1216 unsigned long sep_out_lli_entries,
1217 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)
1219 /* points to the area where next lli table can be allocated */
1220 unsigned long lli_table_alloc_addr;
1221 /* input lli table */
1222 struct sep_lli_entry_t *in_lli_table_ptr;
1223 /* output lli table */
1224 struct sep_lli_entry_t *out_lli_table_ptr;
1225 /* pointer to the info entry of the table - the last entry */
1226 struct sep_lli_entry_t *info_in_entry_ptr;
1227 /* pointer to the info entry of the table - the last entry */
1228 struct sep_lli_entry_t *info_out_entry_ptr;
1229 /* points to the first entry to be processed in the lli_in_array */
1230 unsigned long current_in_entry;
1231 /* points to the first entry to be processed in the lli_out_array */
1232 unsigned long current_out_entry;
1233 /* max size of the input table */
1234 unsigned long in_table_data_size;
1235 /* max size of the output table */
1236 unsigned long out_table_data_size;
1237 /* flag te signifies if this is the first tables build from the arrays */
1238 unsigned long first_table_flag;
1239 /* the data size that should be in table */
1240 unsigned long table_data_size;
1241 /* number of etnries in the input table */
1242 unsigned long num_entries_in_table;
1243 /* number of etnries in the output table */
1244 unsigned long num_entries_out_table;
1246 dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1248 /* initiate to pint after the message area */
1249 lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1251 current_in_entry = 0;
1252 current_out_entry = 0;
1253 first_table_flag = 1;
1254 info_in_entry_ptr = 0;
1255 info_out_entry_ptr = 0;
1257 /* loop till all the entries in in array are not processed */
1258 while (current_in_entry < sep_in_lli_entries) {
1259 /* set the new input and output tables */
1260 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
1262 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1264 /* set the first output tables */
1265 out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
1267 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1269 /* calculate the maximum size of data for input table */
1270 in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry));
1272 /* calculate the maximum size of data for output table */
1273 out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry));
1275 edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1276 edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1278 /* check where the data is smallest */
1279 table_data_size = in_table_data_size;
1280 if (table_data_size > out_table_data_size)
1281 table_data_size = out_table_data_size;
1283 /* now calculate the table size so that it will be module block size */
1284 table_data_size = (table_data_size / block_size) * block_size;
1286 dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
1288 /* construct input lli table */
1289 sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, ¤t_in_entry, &num_entries_in_table, table_data_size);
1291 /* construct output lli table */
1292 sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, ¤t_out_entry, &num_entries_out_table, table_data_size);
1294 /* if info entry is null - this is the first table built */
1295 if (info_in_entry_ptr == 0) {
1296 /* set the output parameters to physical addresses */
1297 *lli_table_in_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
1298 *in_num_entries_ptr = num_entries_in_table;
1299 *lli_table_out_ptr = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
1300 *out_num_entries_ptr = num_entries_out_table;
1301 *table_data_size_ptr = table_data_size;
1303 edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1304 edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1306 /* update the info entry of the previous in table */
1307 info_in_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
1308 info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
1310 /* update the info entry of the previous in table */
1311 info_out_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
1312 info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size);
1315 /* save the pointer to the info entry of the current tables */
1316 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1317 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1319 edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table);
1320 edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr);
1321 edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr);
1324 /* print input tables */
1325 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1326 sep_shared_area_phys_to_virt(*lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr);
1327 /* print output tables */
1328 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1329 sep_shared_area_phys_to_virt(*lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr);
1330 dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1336 This function builds input and output DMA tables for synhronic
1337 symmetric operations (AES, DES). It also checks that each table
1338 is of the modular block size
1340 static int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
1341 unsigned long app_virt_out_addr,
1342 unsigned long data_size,
1343 unsigned long block_size,
1344 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)
1346 /* array of pointers of page */
1347 struct sep_lli_entry_t *lli_in_array;
1348 /* array of pointers of page */
1349 struct sep_lli_entry_t *lli_out_array;
1352 dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1354 /* initialize the pages pointers */
1355 sep_dev->in_page_array = 0;
1356 sep_dev->out_page_array = 0;
1358 /* check if the pages are in Kernel Virtual Address layout */
1359 if (isKernelVirtualAddress == true) {
1360 /* lock the pages of the kernel buffer and translate them to pages */
1361 result = sep_lock_kernel_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
1363 edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1367 /* lock the pages of the user buffer and translate them to pages */
1368 result = sep_lock_user_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
1370 edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1375 if (isKernelVirtualAddress == true) {
1376 result = sep_lock_kernel_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
1378 edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1379 goto end_function_with_error1;
1382 result = sep_lock_user_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
1384 edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1385 goto end_function_with_error1;
1388 edbg("sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1389 edbg("sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1390 edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1393 /* call the fucntion that creates table from the lli arrays */
1394 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);
1396 edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1397 goto end_function_with_error2;
1400 /* fall through - free the lli entry arrays */
1401 dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr);
1402 dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr);
1403 dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr);
1404 end_function_with_error2:
1405 kfree(lli_out_array);
1406 end_function_with_error1:
1407 kfree(lli_in_array);
1409 dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result);
1415 this function handles tha request for creation of the DMA table
1416 for the synchronic symmetric operations (AES,DES)
1418 static int sep_create_sync_dma_tables_handler(unsigned long arg)
1421 /* command arguments */
1422 struct sep_driver_build_sync_table_t command_args;
1424 dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
1426 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
1430 edbg("app_in_address is %08lx\n", command_args.app_in_address);
1431 edbg("app_out_address is %08lx\n", command_args.app_out_address);
1432 edbg("data_size is %lu\n", command_args.data_in_size);
1433 edbg("block_size is %lu\n", command_args.block_size);
1435 /* check if we need to build only input table or input/output */
1436 if (command_args.app_out_address)
1437 /* prepare input and output tables */
1438 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
1439 command_args.app_out_address,
1440 command_args.data_in_size,
1441 command_args.block_size,
1442 &command_args.in_table_address,
1443 &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);
1445 /* prepare input tables */
1446 error = sep_prepare_input_dma_table(command_args.app_in_address,
1447 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);
1452 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t));
1454 dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
1459 this function handles the request for freeing dma table for synhronic actions
1461 static int sep_free_dma_table_data_handler(void)
1463 dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
1465 /* free input pages array */
1466 sep_free_dma_pages(sep_dev->in_page_array, sep_dev->in_num_pages, 0);
1468 /* free output pages array if needed */
1469 if (sep_dev->out_page_array)
1470 sep_free_dma_pages(sep_dev->out_page_array, sep_dev->out_num_pages, 1);
1472 /* reset all the values */
1473 sep_dev->in_page_array = 0;
1474 sep_dev->out_page_array = 0;
1475 sep_dev->in_num_pages = 0;
1476 sep_dev->out_num_pages = 0;
1477 dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
1482 this function find a space for the new flow dma table
1484 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr)
1487 /* pointer to the id field of the flow dma table */
1488 unsigned long *start_table_ptr;
1489 unsigned long flow_dma_area_start_addr;
1490 unsigned long flow_dma_area_end_addr;
1491 /* maximum table size in words */
1492 unsigned long table_size_in_words;
1494 /* find the start address of the flow DMA table area */
1495 flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1497 /* set end address of the flow table area */
1498 flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
1500 /* set table size in words */
1501 table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
1503 /* set the pointer to the start address of DMA area */
1504 start_table_ptr = (unsigned long *) flow_dma_area_start_addr;
1506 /* find the space for the next table */
1507 while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr))
1508 start_table_ptr += table_size_in_words;
1510 /* check if we reached the end of floa tables area */
1511 if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr)
1514 *table_address_ptr = start_table_ptr;
1522 This function creates one DMA table for flow and returns its data,
1523 and pointer to its info entry
1525 static 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)
1528 /* the range in pages */
1529 unsigned long lli_array_size;
1530 struct sep_lli_entry_t *lli_array;
1531 struct sep_lli_entry_t *flow_dma_table_entry_ptr;
1532 unsigned long *start_dma_table_ptr;
1533 /* total table data counter */
1534 unsigned long dma_table_data_count;
1535 /* pointer that will keep the pointer to the pages of the virtual buffer */
1536 struct page **page_array_ptr;
1537 unsigned long entry_count;
1539 /* find the space for the new table */
1540 error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
1544 /* check if the pages are in Kernel Virtual Address layout */
1545 if (isKernelVirtualAddress == true)
1546 /* lock kernel buffer in the memory */
1547 error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
1549 /* lock user buffer in the memory */
1550 error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
1555 /* set the pointer to page array at the beginning of table - this table is
1556 now considered taken */
1557 *start_dma_table_ptr = lli_array_size;
1559 /* point to the place of the pages pointers of the table */
1560 start_dma_table_ptr++;
1562 /* set the pages pointer */
1563 *start_dma_table_ptr = (unsigned long) page_array_ptr;
1565 /* set the pointer to the first entry */
1566 flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr);
1568 /* now create the entries for table */
1569 for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) {
1570 flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address;
1572 flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size;
1574 /* set the total data of a table */
1575 dma_table_data_count += lli_array[entry_count].block_size;
1577 flow_dma_table_entry_ptr++;
1580 /* set the physical address */
1581 table_data->physical_address = virt_to_phys(start_dma_table_ptr);
1583 /* set the num_entries and total data size */
1584 table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count);
1586 /* set the info entry */
1587 flow_dma_table_entry_ptr->physical_address = 0xffffffff;
1588 flow_dma_table_entry_ptr->block_size = 0;
1590 /* set the pointer to info entry */
1591 *info_entry_ptr = flow_dma_table_entry_ptr;
1593 /* the array of the lli entries */
1602 This function creates a list of tables for flow and returns the data for
1603 the first and last tables of the list
1605 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
1606 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)
1609 unsigned long virt_buff_addr;
1610 unsigned long virt_buff_size;
1611 struct sep_lli_entry_t table_data;
1612 struct sep_lli_entry_t *info_entry_ptr;
1613 struct sep_lli_entry_t *prev_info_entry_ptr;
1618 prev_info_entry_ptr = 0;
1620 /* init the first table to default */
1621 table_data.physical_address = 0xffffffff;
1622 first_table_data_ptr->physical_address = 0xffffffff;
1623 table_data.block_size = 0;
1625 for (i = 0; i < num_virtual_buffers; i++) {
1626 /* get the virtual buffer address */
1627 error = get_user(virt_buff_addr, &first_buff_addr);
1631 /* get the virtual buffer size */
1633 error = get_user(virt_buff_size, &first_buff_addr);
1637 /* advance the address to point to the next pair of address|size */
1640 /* now prepare the one flow LLI table from the data */
1641 error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress);
1646 /* if this is the first table - save it to return to the user
1648 *first_table_data_ptr = table_data;
1650 /* set the pointer to info entry */
1651 prev_info_entry_ptr = info_entry_ptr;
1653 /* not first table - the previous table info entry should
1655 prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size);
1657 /* set the pointer to info entry */
1658 prev_info_entry_ptr = info_entry_ptr;
1662 /* set the last table data */
1663 *last_table_data_ptr = table_data;
1669 this function goes over all the flow tables connected to the given
1670 table and deallocate them
1672 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
1675 unsigned long *table_ptr;
1676 /* end address of the flow dma area */
1677 unsigned long num_entries;
1678 unsigned long num_pages;
1679 struct page **pages_ptr;
1680 /* maximum table size in words */
1681 struct sep_lli_entry_t *info_entry_ptr;
1683 /* set the pointer to the first table */
1684 table_ptr = (unsigned long *) first_table_ptr->physical_address;
1686 /* set the num of entries */
1687 num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
1688 & SEP_NUM_ENTRIES_MASK;
1690 /* go over all the connected tables */
1691 while (*table_ptr != 0xffffffff) {
1692 /* get number of pages */
1693 num_pages = *(table_ptr - 2);
1695 /* get the pointer to the pages */
1696 pages_ptr = (struct page **) (*(table_ptr - 1));
1698 /* free the pages */
1699 sep_free_dma_pages(pages_ptr, num_pages, 1);
1701 /* goto to the info entry */
1702 info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1);
1704 table_ptr = (unsigned long *) info_entry_ptr->physical_address;
1705 num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1712 This function returns pointer to the flow data structure
1713 that contains the given id
1715 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr)
1717 unsigned long count;
1721 always search for flow with id default first - in case we
1722 already started working on the flow there can be no situation
1723 when 2 flows are with default flag
1725 for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
1726 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
1727 *flow_data_ptr = &sep_dev->flows_data_array[count];
1732 if (count == SEP_DRIVER_NUM_FLOWS)
1741 this function handles the request to create the DMA tables for flow
1743 static int sep_create_flow_dma_tables_handler(unsigned long arg)
1746 struct sep_driver_build_flow_table_t command_args;
1747 /* first table - output */
1748 struct sep_lli_entry_t first_table_data;
1749 /* dma table data */
1750 struct sep_lli_entry_t last_table_data;
1751 /* pointer to the info entry of the previuos DMA table */
1752 struct sep_lli_entry_t *prev_info_entry_ptr;
1753 /* pointer to the flow data strucutre */
1754 struct sep_flow_context_t *flow_context_ptr;
1756 dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
1758 /* init variables */
1759 prev_info_entry_ptr = 0;
1760 first_table_data.physical_address = 0xffffffff;
1762 /* find the free structure for flow data */
1763 error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
1767 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
1771 /* create flow tables */
1772 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);
1774 goto end_function_with_error;
1776 /* check if flow is static */
1777 if (!command_args.flow_type)
1778 /* point the info entry of the last to the info entry of the first */
1779 last_table_data = first_table_data;
1781 /* set output params */
1782 command_args.first_table_addr = first_table_data.physical_address;
1783 command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1784 command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1786 /* send the parameters to user application */
1787 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
1789 goto end_function_with_error;
1791 /* all the flow created - update the flow entry with temp id */
1792 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
1794 /* set the processing tables data in the context */
1795 if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
1796 flow_context_ptr->input_tables_in_process = first_table_data;
1798 flow_context_ptr->output_tables_in_process = first_table_data;
1802 end_function_with_error:
1803 /* free the allocated tables */
1804 sep_deallocated_flow_tables(&first_table_data);
1806 dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
1811 this functio nhandles add tables to flow
1813 static int sep_add_flow_tables_handler(unsigned long arg)
1816 unsigned long num_entries;
1817 struct sep_driver_add_flow_table_t command_args;
1818 struct sep_flow_context_t *flow_context_ptr;
1819 /* first dma table data */
1820 struct sep_lli_entry_t first_table_data;
1821 /* last dma table data */
1822 struct sep_lli_entry_t last_table_data;
1823 /* pointer to the info entry of the current DMA table */
1824 struct sep_lli_entry_t *info_entry_ptr;
1826 dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n");
1828 /* get input parameters */
1829 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
1833 /* find the flow structure for the flow id */
1834 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1838 /* prepare the flow dma tables */
1839 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);
1841 goto end_function_with_error;
1843 /* now check if there is already an existing add table for this flow */
1844 if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
1845 /* this buffer was for input buffers */
1846 if (flow_context_ptr->input_tables_flag) {
1847 /* add table already exists - add the new tables to the end
1849 num_entries = (flow_context_ptr->last_input_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1851 info_entry_ptr = (struct sep_lli_entry_t *)
1852 (flow_context_ptr->last_input_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1854 /* connect to list of tables */
1855 *info_entry_ptr = first_table_data;
1857 /* set the first table data */
1858 first_table_data = flow_context_ptr->first_input_table;
1860 /* set the input flag */
1861 flow_context_ptr->input_tables_flag = 1;
1863 /* set the first table data */
1864 flow_context_ptr->first_input_table = first_table_data;
1866 /* set the last table data */
1867 flow_context_ptr->last_input_table = last_table_data;
1868 } else { /* this is output tables */
1870 /* this buffer was for input buffers */
1871 if (flow_context_ptr->output_tables_flag) {
1872 /* add table already exists - add the new tables to
1873 the end of the previous */
1874 num_entries = (flow_context_ptr->last_output_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1876 info_entry_ptr = (struct sep_lli_entry_t *)
1877 (flow_context_ptr->last_output_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1879 /* connect to list of tables */
1880 *info_entry_ptr = first_table_data;
1882 /* set the first table data */
1883 first_table_data = flow_context_ptr->first_output_table;
1885 /* set the input flag */
1886 flow_context_ptr->output_tables_flag = 1;
1888 /* set the first table data */
1889 flow_context_ptr->first_output_table = first_table_data;
1891 /* set the last table data */
1892 flow_context_ptr->last_output_table = last_table_data;
1895 /* set output params */
1896 command_args.first_table_addr = first_table_data.physical_address;
1897 command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1898 command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1900 /* send the parameters to user application */
1901 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
1902 end_function_with_error:
1903 /* free the allocated tables */
1904 sep_deallocated_flow_tables(&first_table_data);
1906 dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
1911 this function add the flow add message to the specific flow
1913 static int sep_add_flow_tables_message_handler(unsigned long arg)
1916 struct sep_driver_add_message_t command_args;
1917 struct sep_flow_context_t *flow_context_ptr;
1919 dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
1921 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
1926 if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
1931 /* find the flow context */
1932 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1936 /* copy the message into context */
1937 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
1938 error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
1940 dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
1946 this function returns the physical and virtual addresses of the static pool
1948 static int sep_get_static_pool_addr_handler(unsigned long arg)
1951 struct sep_driver_static_pool_addr_t command_args;
1953 dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
1955 /*prepare the output parameters in the struct */
1956 command_args.physical_static_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
1957 command_args.virtual_static_address = sep_dev->shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
1959 edbg("SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
1961 /* send the parameters to user application */
1962 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
1963 dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
1968 this address gets the offset of the physical address from the start
1971 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
1974 struct sep_driver_get_mapped_offset_t command_args;
1976 dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
1978 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
1982 if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
1987 /*prepare the output parameters in the struct */
1988 command_args.offset = command_args.physical_address - sep_dev->phys_shared_area_addr;
1990 edbg("SEP Driver:physical_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
1992 /* send the parameters to user application */
1993 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
1995 dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2003 static int sep_start_handler(void)
2005 unsigned long reg_val;
2006 unsigned long error = 0;
2008 dbg("SEP Driver:--------> sep_start_handler start\n");
2010 /* wait in polling for message from SEP */
2012 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2015 /* check the value */
2017 /* fatal error - read erro status from GPRO */
2018 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2019 dbg("SEP Driver:<-------- sep_start_handler end\n");
2024 this function handles the request for SEP initialization
2026 static int sep_init_handler(unsigned long arg)
2028 unsigned long message_word;
2029 unsigned long *message_ptr;
2030 struct sep_driver_init_t command_args;
2031 unsigned long counter;
2032 unsigned long error;
2033 unsigned long reg_val;
2035 dbg("SEP Driver:--------> sep_init_handler start\n");
2038 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
2040 dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
2045 /* PATCH - configure the DMA to single -burst instead of multi-burst */
2046 /*sep_configure_dma_burst(); */
2048 dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
2050 message_ptr = (unsigned long *) command_args.message_addr;
2052 /* set the base address of the SRAM */
2053 sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
2055 for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) {
2056 get_user(message_word, message_ptr);
2057 /* write data to SRAM */
2058 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR, message_word);
2059 edbg("SEP Driver:message_word is %lu\n", message_word);
2060 /* wait for write complete */
2061 sep_wait_sram_write(sep_dev);
2063 dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
2065 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
2068 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2069 while (!(reg_val & 0xFFFFFFFD));
2071 dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
2073 /* check the value */
2074 if (reg_val == 0x1) {
2075 edbg("SEP Driver:init failed\n");
2077 error = sep_read_reg(sep_dev, 0x8060);
2078 edbg("SEP Driver:sw monitor is %lu\n", error);
2080 /* fatal error - read erro status from GPRO */
2081 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2082 edbg("SEP Driver:error is %lu\n", error);
2085 dbg("SEP Driver:<-------- sep_init_handler end\n");
2091 this function handles the request cache and resident reallocation
2093 static int sep_realloc_cache_resident_handler(unsigned long arg)
2096 unsigned long phys_cache_address;
2097 unsigned long phys_resident_address;
2098 struct sep_driver_realloc_cache_resident_t command_args;
2101 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_realloc_cache_resident_t));
2105 /* copy cache and resident to the their intended locations */
2106 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);
2110 command_args.new_base_addr = sep_dev->phys_shared_area_addr;
2112 /* find the new base address according to the lowest address between
2113 cache, resident and shared area */
2114 if (phys_resident_address < command_args.new_base_addr)
2115 command_args.new_base_addr = phys_resident_address;
2116 if (phys_cache_address < command_args.new_base_addr)
2117 command_args.new_base_addr = phys_cache_address;
2119 /* set the return parameters */
2120 command_args.new_cache_addr = phys_cache_address;
2121 command_args.new_resident_addr = phys_resident_address;
2123 /* set the new shared area */
2124 command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
2126 edbg("SEP Driver:command_args.new_shared_area_addr is %08lx\n", command_args.new_shared_area_addr);
2127 edbg("SEP Driver:command_args.new_base_addr is %08lx\n", command_args.new_base_addr);
2128 edbg("SEP Driver:command_args.new_resident_addr is %08lx\n", command_args.new_resident_addr);
2129 edbg("SEP Driver:command_args.new_cache_addr is %08lx\n", command_args.new_cache_addr);
2131 /* return to user */
2132 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_realloc_cache_resident_t));
2138 this function handles the request for get time
2140 static int sep_get_time_handler(unsigned long arg)
2143 struct sep_driver_get_time_t command_args;
2145 error = sep_set_time(&command_args.time_physical_address, &command_args.time_value);
2146 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_get_time_t));
2152 This api handles the setting of API mode to blocking or non-blocking
2154 static int sep_set_api_mode_handler(unsigned long arg)
2157 unsigned long mode_flag;
2159 dbg("SEP Driver:--------> sep_set_api_mode_handler start\n");
2161 error = get_user(mode_flag, &(((struct sep_driver_set_api_mode_t *) arg)->mode));
2165 /* set the global flag */
2166 sep_dev->block_mode_flag = mode_flag;
2168 dbg("SEP Driver:<-------- sep_set_api_mode_handler end\n");
2173 This API handles the end transaction request
2175 static int sep_end_transaction_handler(unsigned long arg)
2177 dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
2179 #if 0 /*!SEP_DRIVER_POLLING_MODE */
2181 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
2183 /* release IRQ line */
2184 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
2186 /* lock the sep mutex */
2187 mutex_unlock(&sep_mutex);
2190 dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
2197 This function handler the set flow id command
2199 static int sep_set_flow_id_handler(unsigned long arg)
2202 unsigned long flow_id;
2203 struct sep_flow_context_t *flow_data_ptr;
2205 dbg("------------>SEP Driver: sep_set_flow_id_handler start\n");
2207 error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id));
2211 /* find the flow data structure that was just used for creating new flow
2212 - its id should be default */
2213 error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
2218 flow_data_ptr->flow_id = flow_id;
2221 dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n");
2229 static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
2233 dbg("------------>SEP Driver: ioctl start\n");
2235 edbg("SEP Driver: cmd is %x\n", cmd);
2237 /* check that the command is for sep device */
2238 if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
2242 case SEP_IOCSENDSEPCOMMAND:
2243 /* send command to SEP */
2244 sep_send_command_handler();
2245 edbg("SEP Driver: after sep_send_command_handler\n");
2247 case SEP_IOCSENDSEPRPLYCOMMAND:
2248 /* send reply command to SEP */
2249 sep_send_reply_command_handler();
2251 case SEP_IOCALLOCDATAPOLL:
2252 /* allocate data pool */
2253 error = sep_allocate_data_pool_memory_handler(arg);
2255 case SEP_IOCWRITEDATAPOLL:
2256 /* write data into memory pool */
2257 error = sep_write_into_data_pool_handler(arg);
2259 case SEP_IOCREADDATAPOLL:
2260 /* read data from data pool into application memory */
2261 error = sep_read_from_data_pool_handler(arg);
2263 case SEP_IOCCREATESYMDMATABLE:
2264 /* create dma table for synhronic operation */
2265 error = sep_create_sync_dma_tables_handler(arg);
2267 case SEP_IOCCREATEFLOWDMATABLE:
2268 /* create flow dma tables */
2269 error = sep_create_flow_dma_tables_handler(arg);
2271 case SEP_IOCFREEDMATABLEDATA:
2272 /* free the pages */
2273 error = sep_free_dma_table_data_handler();
2275 case SEP_IOCSETFLOWID:
2277 error = sep_set_flow_id_handler(arg);
2279 case SEP_IOCADDFLOWTABLE:
2280 /* add tables to the dynamic flow */
2281 error = sep_add_flow_tables_handler(arg);
2283 case SEP_IOCADDFLOWMESSAGE:
2284 /* add message of add tables to flow */
2285 error = sep_add_flow_tables_message_handler(arg);
2287 case SEP_IOCSEPSTART:
2288 /* start command to sep */
2289 error = sep_start_handler();
2291 case SEP_IOCSEPINIT:
2292 /* init command to sep */
2293 error = sep_init_handler(arg);
2295 case SEP_IOCSETAPIMODE:
2296 /* set non- blocking mode */
2297 error = sep_set_api_mode_handler(arg);
2299 case SEP_IOCGETSTATICPOOLADDR:
2300 /* get the physical and virtual addresses of the static pool */
2301 error = sep_get_static_pool_addr_handler(arg);
2303 case SEP_IOCENDTRANSACTION:
2304 error = sep_end_transaction_handler(arg);
2306 case SEP_IOCREALLOCCACHERES:
2307 error = sep_realloc_cache_resident_handler(arg);
2309 case SEP_IOCGETMAPPEDADDROFFSET:
2310 error = sep_get_physical_mapped_offset_handler(arg);
2313 error = sep_get_time_handler(arg);
2319 dbg("SEP Driver:<-------- ioctl end\n");
2325 #if !SEP_DRIVER_POLLING_MODE
2327 /* handler for flow done interrupt */
2329 static void sep_flow_done_handler(struct work_struct *work)
2331 struct sep_flow_context_t *flow_data_ptr;
2333 /* obtain the mutex */
2334 mutex_lock(&sep_mutex);
2336 /* get the pointer to context */
2337 flow_data_ptr = (struct sep_flow_context_t *) work;
2339 /* free all the current input tables in sep */
2340 sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
2342 /* free all the current tables output tables in SEP (if needed) */
2343 if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
2344 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
2346 /* check if we have additional tables to be sent to SEP only input
2347 flag may be checked */
2348 if (flow_data_ptr->input_tables_flag) {
2349 /* copy the message to the shared RAM and signal SEP */
2350 memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes);
2352 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
2354 mutex_unlock(&sep_mutex);
2357 interrupt handler function
2359 static irqreturn_t sep_inthandler(int irq, void *dev_id)
2361 irqreturn_t int_error;
2362 unsigned long error;
2363 unsigned long reg_val;
2364 unsigned long flow_id;
2365 struct sep_flow_context_t *flow_context_ptr;
2367 int_error = IRQ_HANDLED;
2369 /* read the IRR register to check if this is SEP interrupt */
2370 reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
2371 edbg("SEP Interrupt - reg is %08lx\n", reg_val);
2373 /* check if this is the flow interrupt */
2374 if (0 /*reg_val & (0x1 << 11) */ ) {
2375 /* read GPRO to find out the which flow is done */
2376 flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
2378 /* find the contex of the flow */
2379 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
2381 goto end_function_with_error;
2383 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
2385 /* queue the work */
2386 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
2389 /* check if this is reply interrupt from SEP */
2390 if (reg_val & (0x1 << 13)) {
2391 /* update the counter of reply messages */
2392 sep_dev->sep_to_host_reply_counter++;
2394 /* wake up the waiting process */
2395 wake_up(&g_sep_event);
2397 int_error = IRQ_NONE;
2401 end_function_with_error:
2402 /* clear the interrupt */
2403 sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
2414 static void sep_wait_busy(struct sep_device *dev)
2419 reg = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
2424 PATCH for configuring the DMA to single burst instead of multi-burst
2426 static void sep_configure_dma_burst(void)
2428 #define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL
2430 dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
2432 /* request access to registers from SEP */
2433 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2435 dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n");
2437 sep_wait_busy(sep_dev);
2439 dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n");
2441 /* set the DMA burst register to single burst */
2442 sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
2444 /* release the sep busy */
2445 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
2446 sep_wait_busy(sep_dev);
2448 dbg("SEP Driver:<-------- sep_configure_dma_burst done \n");
2453 function that is activaed on the succesfull probe of the SEP device
2455 static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2459 edbg("Sep pci probe starting\n");
2461 /* enable the device */
2462 error = pci_enable_device(pdev);
2464 edbg("error enabling pci device\n");
2468 /* set the pci dev pointer */
2469 sep_dev->sep_pci_dev_ptr = pdev;
2471 /* get the io memory start address */
2472 sep_dev->io_memory_start_physical_address = pci_resource_start(pdev, 0);
2473 if (!sep_dev->io_memory_start_physical_address) {
2474 edbg("SEP Driver error pci resource start\n");
2478 /* get the io memory end address */
2479 sep_dev->io_memory_end_physical_address = pci_resource_end(pdev, 0);
2480 if (!sep_dev->io_memory_end_physical_address) {
2481 edbg("SEP Driver error pci resource end\n");
2485 sep_dev->io_memory_size = sep_dev->io_memory_end_physical_address - sep_dev->io_memory_start_physical_address + 1;
2487 edbg("SEP Driver:io_memory_start_physical_address is %08lx\n", sep_dev->io_memory_start_physical_address);
2489 edbg("SEP Driver:io_memory_end_phyaical_address is %08lx\n", sep_dev->io_memory_end_physical_address);
2491 edbg("SEP Driver:io_memory_size is %08lx\n", sep_dev->io_memory_size);
2493 sep_dev->io_memory_start_virtual_address = ioremap_nocache(sep_dev->io_memory_start_physical_address, sep_dev->io_memory_size);
2494 if (!sep_dev->io_memory_start_virtual_address) {
2495 edbg("SEP Driver error ioremap of io memory\n");
2499 edbg("SEP Driver:io_memory_start_virtual_address is %p\n", sep_dev->io_memory_start_virtual_address);
2501 sep_dev->reg_base_address = (void __iomem *) sep_dev->io_memory_start_virtual_address;
2504 /* set up system base address and shared memory location */
2506 sep_dev->rar_virtual_address = kmalloc(2 * SEP_RAR_IO_MEM_REGION_SIZE, GFP_KERNEL);
2508 if (!sep_dev->rar_virtual_address) {
2509 edbg("SEP Driver:cant kmalloc rar\n");
2513 sep_dev->rar_physical_address = __pa(sep_dev->rar_virtual_address);
2515 edbg("SEP Driver:rar_physical is %08lx\n", sep_dev->rar_physical_address);
2516 edbg("SEP Driver:rar_virtual is %p\n", sep_dev->rar_virtual_address);
2518 #if !SEP_DRIVER_POLLING_MODE
2520 edbg("SEP Driver: about to write IMR and ICR REG_ADDR\n");
2522 /* clear ICR register */
2523 sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF);
2525 /* set the IMR register - open only GPR 2 */
2526 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
2528 /* figure out our irq */
2530 error = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, (u8 *) & sep_dev->sep_irq);
2532 edbg("SEP Driver: my irq is %d\n", sep_irq);
2534 edbg("SEP Driver: about to call request_irq\n");
2535 /* get the interrupt line */
2536 error = request_irq(sep_irq, sep_inthandler, IRQF_SHARED, "sep_driver", &sep_dev->reg_base_address);
2541 edbg("SEP Driver: about to write IMR REG_ADDR");
2543 /* set the IMR register - open only GPR 2 */
2544 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
2546 #endif /* SEP_DRIVER_POLLING_MODE */
2551 static struct pci_device_id sep_pci_id_tbl[] = {
2552 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)},
2556 MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl);
2558 /* field for registering driver to PCI device */
2559 static struct pci_driver sep_pci_driver = {
2560 .name = "sep_sec_driver",
2561 .id_table = sep_pci_id_tbl,
2565 /* major and minor device numbers */
2566 static dev_t sep_devno;
2568 /* the files operations structure of the driver */
2569 static struct file_operations sep_file_operations = {
2570 .owner = THIS_MODULE,
2574 .release = sep_release,
2579 /* cdev struct of the driver */
2580 static struct cdev sep_cdev;
2583 this function registers the driver to the file system
2585 static int sep_register_driver_to_fs(void)
2587 int ret_val = alloc_chrdev_region(&sep_devno, 0, 1, "sep_sec_driver");
2589 edbg("sep_driver:major number allocation failed, retval is %d\n", ret_val);
2594 cdev_init(&sep_cdev, &sep_file_operations);
2595 sep_cdev.owner = THIS_MODULE;
2597 /* register the driver with the kernel */
2598 ret_val = cdev_add(&sep_cdev, sep_devno, 1);
2601 edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val);
2602 goto end_function_unregister_devnum;
2607 end_function_unregister_devnum:
2609 /* unregister dev numbers */
2610 unregister_chrdev_region(sep_devno, 1);
2617 /*--------------------------------------------------------------
2619 ----------------------------------------------------------------*/
2620 static int __init sep_init(void)
2624 int size; /* size of memory for allocation */
2626 dbg("SEP Driver:-------->Init start\n");
2627 edbg("sep->shared_area_addr = %lx\n", (unsigned long) &sep_dev->shared_area_addr);
2629 /* transaction counter that coordinates the transactions between SEP
2631 sep_dev->host_to_sep_send_counter = 0;
2633 /* counter for the messages from sep */
2634 sep_dev->sep_to_host_reply_counter = 0;
2636 /* counter for the number of bytes allocated in the pool
2637 for the current transaction */
2638 sep_dev->data_pool_bytes_allocated = 0;
2640 /* set the starting mode to blocking */
2641 sep_dev->block_mode_flag = 1;
2643 /* FIXME: Probe can occur before we are ready to survive a probe */
2644 ret_val = pci_register_driver(&sep_pci_driver);
2646 edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val);
2647 goto end_function_unregister_from_fs;
2649 /* calculate the total size for allocation */
2650 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
2651 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;
2653 /* allocate the shared area */
2654 if (sep_map_and_alloc_shared_area(size, &sep_dev->shared_area_addr, &sep_dev->phys_shared_area_addr)) {
2656 /* allocation failed */
2657 goto end_function_unmap_io_memory;
2659 /* now set the memory regions */
2660 sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
2662 edbg("SEP Driver: g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
2664 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
2665 /* send the new SHARED MESSAGE AREA to the SEP */
2666 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep_dev->phys_shared_area_addr);
2668 /* poll for SEP response */
2669 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
2670 while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
2671 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
2673 /* check the return value (register) */
2674 if (retVal != sep_dev->phys_shared_area_addr) {
2676 goto end_function_deallocate_message_area;
2679 /* init the flow contextes */
2680 for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
2681 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
2683 sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
2684 if (sep_dev->flow_wq_ptr == 0) {
2686 edbg("sep_driver:flow queue creation failed\n");
2687 goto end_function_deallocate_sep_shared_area;
2689 edbg("SEP Driver: create flow workqueue \n");
2691 /* register driver to fs */
2692 ret_val = sep_register_driver_to_fs();
2694 goto end_function_deallocate_sep_shared_area;
2695 /* load the rom code */
2696 sep_load_rom_code();
2698 end_function_unregister_from_fs:
2699 /* unregister from fs */
2700 cdev_del(&sep_cdev);
2701 /* unregister dev numbers */
2702 unregister_chrdev_region(sep_devno, 1);
2703 end_function_deallocate_sep_shared_area:
2704 /* de-allocate shared area */
2705 sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
2706 end_function_unmap_io_memory:
2707 iounmap((void *) sep_dev->reg_base_address);
2708 /* release io memory region */
2709 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
2711 dbg("SEP Driver:<-------- Init end\n");
2716 /*-------------------------------------------------------------
2718 --------------------------------------------------------------*/
2719 static void __exit sep_exit(void)
2723 dbg("SEP Driver:--------> Exit start\n");
2725 /* unregister from fs */
2726 cdev_del(&sep_cdev);
2727 /* unregister dev numbers */
2728 unregister_chrdev_region(sep_devno, 1);
2729 /* calculate the total size for de-allocation */
2730 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
2731 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;
2732 /* free shared area */
2733 sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
2734 edbg("SEP Driver: free pages SEP SHARED AREA \n");
2735 iounmap((void *) sep_dev->reg_base_address);
2736 edbg("SEP Driver: iounmap \n");
2737 /* release io memory region */
2738 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
2739 edbg("SEP Driver: release_mem_region \n");
2740 dbg("SEP Driver:<-------- Exit end\n");
2744 module_init(sep_init);
2745 module_exit(sep_exit);
2747 MODULE_LICENSE("GPL");