diff options
author | Alan Cox <alan@linux.intel.com> | 2009-08-07 19:23:50 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-15 12:02:13 -0700 |
commit | 0a18d7b5f36f3c77a239ee752c4ce1197af7b617 (patch) | |
tree | 4988d40d13c1ef3f6ec9c22acadf5519b99278d3 /drivers/staging/sep | |
parent | 91410066476f050121b6dc496aaa1a589e82dc21 (diff) | |
download | op-kernel-dev-0a18d7b5f36f3c77a239ee752c4ce1197af7b617.zip op-kernel-dev-0a18d7b5f36f3c77a239ee752c4ce1197af7b617.tar.gz |
Staging: sep: forward declaration removal time
Exterminate! Exterminate! Exterminate!
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/sep')
-rw-r--r-- | drivers/staging/sep/sep_driver.c | 2183 | ||||
-rw-r--r-- | drivers/staging/sep/sep_driver_api.h | 42 | ||||
-rw-r--r-- | drivers/staging/sep/sep_driver_ext_api.h | 84 |
3 files changed, 998 insertions, 1311 deletions
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c index 23bc8a81..fe46c1b 100644 --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -184,199 +184,6 @@ static DEFINE_MUTEX(sep_mutex); /* wait queue head (event) of the driver */ static DECLARE_WAIT_QUEUE_HEAD(g_sep_event); - - -/*------------------------------------------------ - PROTOTYPES ----------------------------------------------------*/ - -/* - this function registers the driver to the file system -*/ -static int sep_register_driver_to_fs(void); - -/* - this function calculates the size of data that can be inserted into the lli - table from this array the condition is that either the table is full - (all etnries are entered), or there are no more entries in the lli array -*/ -static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries); -/* - this functions builds ont lli table from the lli_array according to the - given size of data -*/ -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); - -/* - this function goes over the list of the print created tables and prints - all the data -*/ -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); - - - -/* - This function raises interrupt to SEPm that signals that is has a new - command from HOST -*/ -static void sep_send_command_handler(void); - - -/* - This function raises interrupt to SEP that signals that is has a - new reply from HOST -*/ -static void sep_send_reply_command_handler(void); - -/* - This function handles the allocate data pool memory request - This function returns calculates the physical address of the allocated memory - and the offset of this area from the mapped address. Therefore, the FVOs in - user space can calculate the exact virtual address of this allocated memory -*/ -static int sep_allocate_data_pool_memory_handler(unsigned long arg); - - -/* - This function handles write into allocated data pool command -*/ -static int sep_write_into_data_pool_handler(unsigned long arg); - -/* - this function handles the read from data pool command -*/ -static int sep_read_from_data_pool_handler(unsigned long arg); - -/* - this function handles tha request for creation of the DMA table - for the synchronic symmetric operations (AES,DES) -*/ -static int sep_create_sync_dma_tables_handler(unsigned long arg); - -/* - this function handles the request to create the DMA tables for flow -*/ -static int sep_create_flow_dma_tables_handler(unsigned long arg); - -/* - This API handles the end transaction request -*/ -static int sep_end_transaction_handler(unsigned long arg); - - -/* - this function handles add tables to flow -*/ -static int sep_add_flow_tables_handler(unsigned long arg); - -/* - this function add the flow add message to the specific flow -*/ -static int sep_add_flow_tables_message_handler(unsigned long arg); - -/* - this function handles the request for SEP start -*/ -static int sep_start_handler(void); - -/* - this function handles the request for SEP initialization -*/ -static int sep_init_handler(unsigned long arg); - -/* - this function handles the request cache and resident reallocation -*/ -static int sep_realloc_cache_resident_handler(unsigned long arg); - - -/* - This api handles the setting of API mode to blocking or non-blocking -*/ -static int sep_set_api_mode_handler(unsigned long arg); - -/* - This function locks all the physical pages of the kernel virtual buffer - and construct a basic lli array, where each entry holds the physical - page address and the size that application data holds in this physical pages -*/ -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); - -/* - This function creates one DMA table for flow and returns its data, - and pointer to its info entry -*/ -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); - -/* - This function creates a list of tables for flow and returns the data for the - first and last tables of the list -*/ -static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers, - 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); - -/* - this function find a space for the new flow dma table -*/ -static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr); - -/* - this function goes over all the flow tables connected to the given table and - deallocate them -*/ -static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr); - -/* - This function handler the set flow id command -*/ -static int sep_set_flow_id_handler(unsigned long arg); - -/* - This function returns pointer to the flow data structure - that conatins the given id -*/ -static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr); - - -/* - this function returns the physical and virtual addresses of the static pool -*/ -static int sep_get_static_pool_addr_handler(unsigned long arg); - -/* - this address gets the offset of the physical address from the start of - the mapped area -*/ -static int sep_get_physical_mapped_offset_handler(unsigned long arg); - - -/* - this function handles the request for get time -*/ -static int sep_get_time_handler(unsigned long arg); - -/* - calculates time and sets it at the predefined address -*/ -static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr); - -/* - PATCH for configuring the DMA to single burst instead of multi-burst -*/ -static void sep_configure_dma_burst(void); - -/* - This function locks all the physical pages of the - application virtual buffer and construct a basic lli - array, where each entry holds the physical page address - and the size that application data holds in this physical pages -*/ -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); - -/*--------------------------------------------- - FUNCTIONS ------------------------------------------------*/ - /* This functions copies the cache and resident from their source location into destination memory, which is external to Linux VM and is given as @@ -692,187 +499,595 @@ static unsigned int sep_poll(struct file *filp, poll_table * wait) return mask; } +/* + calculates time and sets it at the predefined address +*/ +static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr) +{ + struct timeval time; + /* address of time in the kernel */ + unsigned long time_addr; + + + dbg("SEP Driver:--------> sep_set_time start\n"); + + do_gettimeofday(&time); + + /* set value in the SYSTEM MEMORY offset */ + time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES; + + *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN; + *(unsigned long *) (time_addr + 4) = time.tv_sec; + + edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec); + edbg("SEP Driver:time_addr is %lu\n", time_addr); + edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr); + + /* set the output parameters if needed */ + if (address_ptr) + *address_ptr = sep_shared_area_virt_to_phys(time_addr); + + if (time_in_sec_ptr) + *time_in_sec_ptr = time.tv_sec; + + dbg("SEP Driver:<-------- sep_set_time end\n"); + + return 0; +} + +/* + This function raises interrupt to SEP that signals that is has a new + command from HOST +*/ +static void sep_send_command_handler(void) +{ + unsigned long count; -static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) + dbg("SEP Driver:--------> sep_send_command_handler start\n"); + sep_set_time(0, 0); + + /* flash cache */ + flush_cache_all(); + + for (count = 0; count < 12 * 4; count += 4) + edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count))); + + /* update counter */ + sep_dev->host_to_sep_send_counter++; + /* send interrupt to SEP */ + sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); + dbg("SEP Driver:<-------- sep_send_command_handler end\n"); + return; +} + +/* + This function raises interrupt to SEPm that signals that is has a + new command from HOST +*/ +static void sep_send_reply_command_handler(void) { - int error = 0; + unsigned long count; - dbg("------------>SEP Driver: ioctl start\n"); + dbg("SEP Driver:--------> sep_send_reply_command_handler start\n"); - edbg("SEP Driver: cmd is %x\n", cmd); + /* flash cache */ + flush_cache_all(); + for (count = 0; count < 12 * 4; count += 4) + edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count))); + /* update counter */ + sep_dev->host_to_sep_send_counter++; + /* send the interrupt to SEP */ + sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep_dev->host_to_sep_send_counter); + /* update both counters */ + sep_dev->host_to_sep_send_counter++; + sep_dev->sep_to_host_reply_counter++; + dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n"); +} - /* check that the command is for sep device */ - if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) +/* + This function handles the allocate data pool memory request + This function returns calculates the physical address of the + allocated memory, and the offset of this area from the mapped address. + Therefore, the FVOs in user space can calculate the exact virtual + address of this allocated memory +*/ +static int sep_allocate_data_pool_memory_handler(unsigned long arg) +{ + int error; + struct sep_driver_alloc_t command_args; + + dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n"); + + error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t)); + if (error) + goto end_function; + + /* allocate memory */ + if ((sep_dev->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { error = -ENOTTY; + goto end_function; + } - switch (cmd) { - case SEP_IOCSENDSEPCOMMAND: - /* send command to SEP */ - sep_send_command_handler(); - edbg("SEP Driver: after sep_send_command_handler\n"); - break; - case SEP_IOCSENDSEPRPLYCOMMAND: - /* send reply command to SEP */ - sep_send_reply_command_handler(); - break; - case SEP_IOCALLOCDATAPOLL: - /* allocate data pool */ - error = sep_allocate_data_pool_memory_handler(arg); - break; - case SEP_IOCWRITEDATAPOLL: - /* write data into memory pool */ - error = sep_write_into_data_pool_handler(arg); - break; - case SEP_IOCREADDATAPOLL: - /* read data from data pool into application memory */ - error = sep_read_from_data_pool_handler(arg); - break; - case SEP_IOCCREATESYMDMATABLE: - /* create dma table for synhronic operation */ - error = sep_create_sync_dma_tables_handler(arg); - break; - case SEP_IOCCREATEFLOWDMATABLE: - /* create flow dma tables */ - error = sep_create_flow_dma_tables_handler(arg); - break; - case SEP_IOCFREEDMATABLEDATA: - /* free the pages */ - error = sep_free_dma_table_data_handler(); - break; - case SEP_IOCSETFLOWID: - /* set flow id */ - error = sep_set_flow_id_handler(arg); - break; - case SEP_IOCADDFLOWTABLE: - /* add tables to the dynamic flow */ - error = sep_add_flow_tables_handler(arg); - break; - case SEP_IOCADDFLOWMESSAGE: - /* add message of add tables to flow */ - error = sep_add_flow_tables_message_handler(arg); - break; - case SEP_IOCSEPSTART: - /* start command to sep */ - error = sep_start_handler(); - break; - case SEP_IOCSEPINIT: - /* init command to sep */ - error = sep_init_handler(arg); - break; - case SEP_IOCSETAPIMODE: - /* set non- blocking mode */ - error = sep_set_api_mode_handler(arg); - break; - case SEP_IOCGETSTATICPOOLADDR: - /* get the physical and virtual addresses of the static pool */ - error = sep_get_static_pool_addr_handler(arg); - break; - case SEP_IOCENDTRANSACTION: - error = sep_end_transaction_handler(arg); - break; - case SEP_IOCREALLOCCACHERES: - error = sep_realloc_cache_resident_handler(arg); - break; - case SEP_IOCGETMAPPEDADDROFFSET: - error = sep_get_physical_mapped_offset_handler(arg); - break; - case SEP_IOCGETIME: - error = sep_get_time_handler(arg); - break; - default: + /* set the virtual and physical address */ + command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated; + command_args.phys_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated; + + /* write the memory back to the user space */ + error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t)); + if (error) + goto end_function; + + /* set the allocation */ + sep_dev->data_pool_bytes_allocated += command_args.num_bytes; + +end_function: + dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n"); + return error; +} + +/* + This function handles write into allocated data pool command +*/ +static int sep_write_into_data_pool_handler(unsigned long arg) +{ + int error; + unsigned long virt_address; + unsigned long app_in_address; + unsigned long num_bytes; + unsigned long data_pool_area_addr; + + dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n"); + + /* get the application address */ + error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address)); + if (error) + goto end_function; + + /* get the virtual kernel address address */ + error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address)); + if (error) + goto end_function; + + /* get the number of bytes */ + error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes)); + if (error) + goto end_function; + + /* calculate the start of the data pool */ + data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES; + + + /* check that the range of the virtual kernel address is correct */ + if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) { error = -ENOTTY; - break; + goto end_function; } - dbg("SEP Driver:<-------- ioctl end\n"); + /* copy the application data */ + error = copy_from_user((void *) virt_address, (void *) app_in_address, num_bytes); +end_function: + dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n"); return error; } +/* + this function handles the read from data pool command +*/ +static int sep_read_from_data_pool_handler(unsigned long arg) +{ + int error; + /* virtual address of dest application buffer */ + unsigned long app_out_address; + /* virtual address of the data pool */ + unsigned long virt_address; + unsigned long num_bytes; + unsigned long data_pool_area_addr; + dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n"); -#if !SEP_DRIVER_POLLING_MODE + /* get the application address */ + error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address)); + if (error) + goto end_function; -/* handler for flow done interrupt */ + /* get the virtual kernel address address */ + error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address)); + if (error) + goto end_function; -static void sep_flow_done_handler(struct work_struct *work) + /* get the number of bytes */ + error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes)); + if (error) + goto end_function; + + /* calculate the start of the data pool */ + data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES; + + /* check that the range of the virtual kernel address is correct */ + if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) { + error = -ENOTTY; + goto end_function; + } + + /* copy the application data */ + error = copy_to_user((void *) app_out_address, (void *) virt_address, num_bytes); +end_function: + dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n"); + return error; +} + +/* + This function releases all the application virtual buffer physical pages, + that were previously locked +*/ +static int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag) { - struct sep_flow_context_t *flow_data_ptr; + unsigned long count; - /* obtain the mutex */ - mutex_lock(&sep_mutex); + if (dirtyFlag) { + for (count = 0; count < num_pages; count++) { + /* the out array was written, therefore the data was changed */ + if (!PageReserved(page_array_ptr[count])) + SetPageDirty(page_array_ptr[count]); + page_cache_release(page_array_ptr[count]); + } + } else { + /* free in pages - the data was only read, therefore no update was done + on those pages */ + for (count = 0; count < num_pages; count++) + page_cache_release(page_array_ptr[count]); + } - /* get the pointer to context */ - flow_data_ptr = (struct sep_flow_context_t *) work; + if (page_array_ptr) + /* free the array */ + kfree(page_array_ptr); - /* free all the current input tables in sep */ - sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process); + return 0; +} - /* free all the current tables output tables in SEP (if needed) */ - if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff) - sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process); +/* + This function locks all the physical pages of the kernel virtual buffer + and construct a basic lli array, where each entry holds the physical + page address and the size that application data holds in this physical pages +*/ +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) +{ + int error = 0; + /* the the page of the end address of the user space buffer */ + unsigned long end_page; + /* the page of the start address of the user space buffer */ + unsigned long start_page; + /* the range in pages */ + unsigned long num_pages; + struct sep_lli_entry_t *lli_array; + /* next kernel address to map */ + unsigned long next_kernel_address; + unsigned long count; - /* check if we have additional tables to be sent to SEP only input - flag may be checked */ - if (flow_data_ptr->input_tables_flag) { - /* copy the message to the shared RAM and signal SEP */ - memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes); + dbg("SEP Driver:--------> sep_lock_kernel_pages start\n"); - sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2); + /* set start and end pages and num pages */ + end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT; + start_page = kernel_virt_addr >> PAGE_SHIFT; + num_pages = end_page - start_page + 1; + + edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr); + edbg("SEP Driver: data_size is %lu\n", data_size); + edbg("SEP Driver: start_page is %lx\n", start_page); + edbg("SEP Driver: end_page is %lx\n", end_page); + edbg("SEP Driver: num_pages is %lu\n", num_pages); + + lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC); + if (!lli_array) { + edbg("SEP Driver: kmalloc for lli_array failed\n"); + error = -ENOMEM; + goto end_function; } - mutex_unlock(&sep_mutex); + + /* set the start address of the first page - app data may start not at + the beginning of the page */ + lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr); + + /* check that not all the data is in the first page only */ + if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size) + lli_array[0].block_size = data_size; + else + lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK)); + + /* debug print */ + 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); + + /* advance the address to the start of the next page */ + next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE; + + /* go from the second page to the prev before last */ + for (count = 1; count < (num_pages - 1); count++) { + lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address); + lli_array[count].block_size = PAGE_SIZE; + + 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); + next_kernel_address += PAGE_SIZE; + } + + /* if more then 1 pages locked - then update for the last page size needed */ + if (num_pages > 1) { + /* update the address of the last page */ + lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address); + + /* set the size of the last page */ + lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK); + + if (lli_array[count].block_size == 0) { + dbg("app_virt_addr is %08lx\n", kernel_virt_addr); + dbg("data_size is %lu\n", data_size); + while (1); + } + + 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); + } + /* set output params */ + *lli_array_ptr = lli_array; + *num_pages_ptr = num_pages; + *page_array_ptr = 0; +end_function: + dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n"); + return 0; } + /* - interrupt handler function + This function locks all the physical pages of the application virtual buffer + and construct a basic lli array, where each entry holds the physical page + address and the size that application data holds in this physical pages */ -static irqreturn_t sep_inthandler(int irq, void *dev_id) +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) { - irqreturn_t int_error; - unsigned long error; - unsigned long reg_val; - unsigned long flow_id; - struct sep_flow_context_t *flow_context_ptr; + int error = 0; + /* the the page of the end address of the user space buffer */ + unsigned long end_page; + /* the page of the start address of the user space buffer */ + unsigned long start_page; + /* the range in pages */ + unsigned long num_pages; + struct page **page_array; + struct sep_lli_entry_t *lli_array; + unsigned long count; + int result; - int_error = IRQ_HANDLED; + dbg("SEP Driver:--------> sep_lock_user_pages start\n"); - /* read the IRR register to check if this is SEP interrupt */ - reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR); - edbg("SEP Interrupt - reg is %08lx\n", reg_val); + /* set start and end pages and num pages */ + end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; + start_page = app_virt_addr >> PAGE_SHIFT; + num_pages = end_page - start_page + 1; - /* check if this is the flow interrupt */ - if (0 /*reg_val & (0x1 << 11) */ ) { - /* read GPRO to find out the which flow is done */ - flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR); + edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr); + edbg("SEP Driver: data_size is %lu\n", data_size); + edbg("SEP Driver: start_page is %lu\n", start_page); + edbg("SEP Driver: end_page is %lu\n", end_page); + edbg("SEP Driver: num_pages is %lu\n", num_pages); - /* find the contex of the flow */ - error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr); - if (error) - goto end_function_with_error; + /* allocate array of pages structure pointers */ + page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC); + if (!page_array) { + edbg("SEP Driver: kmalloc for page_array failed\n"); - INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler); + error = -ENOMEM; + goto end_function; + } - /* queue the work */ - queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq); + lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC); + if (!lli_array) { + edbg("SEP Driver: kmalloc for lli_array failed\n"); - } else { - /* check if this is reply interrupt from SEP */ - if (reg_val & (0x1 << 13)) { - /* update the counter of reply messages */ - sep_dev->sep_to_host_reply_counter++; + error = -ENOMEM; + goto end_function_with_error1; + } - /* wake up the waiting process */ - wake_up(&g_sep_event); - } else { - int_error = IRQ_NONE; - goto end_function; + /* convert the application virtual address into a set of physical */ + down_read(¤t->mm->mmap_sem); + result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0); + up_read(¤t->mm->mmap_sem); + + /* check the number of pages locked - if not all then exit with error */ + if (result != num_pages) { + dbg("SEP Driver: not all pages locked by get_user_pages\n"); + + error = -ENOMEM; + goto end_function_with_error2; + } + + /* flush the cache */ + for (count = 0; count < num_pages; count++) + flush_dcache_page(page_array[count]); + + /* set the start address of the first page - app data may start not at + the beginning of the page */ + lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK)); + + /* check that not all the data is in the first page only */ + if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) + lli_array[0].block_size = data_size; + else + lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); + + /* debug print */ + 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); + + /* go from the second page to the prev before last */ + for (count = 1; count < (num_pages - 1); count++) { + lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]); + lli_array[count].block_size = PAGE_SIZE; + + 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); + } + + /* if more then 1 pages locked - then update for the last page size needed */ + if (num_pages > 1) { + /* update the address of the last page */ + lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]); + + /* set the size of the last page */ + lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK); + + if (lli_array[count].block_size == 0) { + dbg("app_virt_addr is %08lx\n", app_virt_addr); + dbg("data_size is %lu\n", data_size); + while (1); } + 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); } -end_function_with_error: - /* clear the interrupt */ - sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val); + + /* set output params */ + *lli_array_ptr = lli_array; + *num_pages_ptr = num_pages; + *page_array_ptr = page_array; + goto end_function; + +end_function_with_error2: + /* release the cache */ + for (count = 0; count < num_pages; count++) + page_cache_release(page_array[count]); + kfree(lli_array); +end_function_with_error1: + kfree(page_array); end_function: - return int_error; + dbg("SEP Driver:<-------- sep_lock_user_pages end\n"); + return 0; +} + + +/* + this function calculates the size of data that can be inserted into the lli + table from this array the condition is that either the table is full + (all etnries are entered), or there are no more entries in the lli array +*/ +static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries) +{ + unsigned long table_data_size = 0; + unsigned long counter; + + /* calculate the data in the out lli table if till we fill the whole + table or till the data has ended */ + for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++) + table_data_size += lli_in_array_ptr[counter].block_size; + return table_data_size; +} + +/* + this functions builds ont lli table from the lli_array according to + the given size of data +*/ +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) +{ + unsigned long curr_table_data_size; + /* counter of lli array entry */ + unsigned long array_counter; + + dbg("SEP Driver:--------> sep_build_lli_table start\n"); + + /* init currrent table data size and lli array entry counter */ + curr_table_data_size = 0; + array_counter = 0; + *num_table_entries_ptr = 1; + + edbg("SEP Driver:table_data_size is %lu\n", table_data_size); + + /* fill the table till table size reaches the needed amount */ + while (curr_table_data_size < table_data_size) { + /* update the number of entries in table */ + (*num_table_entries_ptr)++; + + lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address; + lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size; + curr_table_data_size += lli_table_ptr->block_size; + + edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr); + edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); + edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); + + /* check for overflow of the table data */ + if (curr_table_data_size > table_data_size) { + edbg("SEP Driver:curr_table_data_size > table_data_size\n"); + + /* update the size of block in the table */ + lli_table_ptr->block_size -= (curr_table_data_size - table_data_size); + + /* update the physical address in the lli array */ + lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size; + + /* update the block size left in the lli array */ + lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size); + } else + /* advance to the next entry in the lli_array */ + array_counter++; + + edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); + edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); + + /* move to the next entry in table */ + lli_table_ptr++; + } + + /* set the info entry to default */ + lli_table_ptr->physical_address = 0xffffffff; + lli_table_ptr->block_size = 0; + + edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr); + edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); + edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); + + /* set the output parameter */ + *num_processed_entries_ptr += array_counter; + + edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr); + dbg("SEP Driver:<-------- sep_build_lli_table end\n"); + return; +} + +/* + this function goes over the list of the print created tables and + prints all the data +*/ +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) +{ + unsigned long table_count; + unsigned long entries_count; + + dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n"); + + table_count = 1; + while ((unsigned long) lli_table_ptr != 0xffffffff) { + edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size); + edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries); + + /* print entries of the table (without info entry) */ + for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) { + edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr); + edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size); + } + + /* point to the info entry */ + lli_table_ptr--; + + edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); + edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); + + + table_data_size = lli_table_ptr->block_size & 0xffffff; + num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff; + lli_table_ptr = (struct sep_lli_entry_t *) + (lli_table_ptr->physical_address); + + 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); + + if ((unsigned long) lli_table_ptr != 0xffffffff) + lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_area_phys_to_virt((unsigned long) lli_table_ptr); + + table_count++; + } + dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n"); } -#endif /* This function prepares only input DMA table for synhronic symmetric @@ -992,86 +1207,6 @@ end_function: } /* - This function builds input and output DMA tables for synhronic - symmetric operations (AES, DES). It also checks that each table - is of the modular block size -*/ -static int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr, - unsigned long app_virt_out_addr, - unsigned long data_size, - 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, bool isKernelVirtualAddress) -{ - /* array of pointers of page */ - struct sep_lli_entry_t *lli_in_array; - /* array of pointers of page */ - struct sep_lli_entry_t *lli_out_array; - int result = 0; - - dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n"); - - /* initialize the pages pointers */ - sep_dev->in_page_array = 0; - sep_dev->out_page_array = 0; - - /* check if the pages are in Kernel Virtual Address layout */ - if (isKernelVirtualAddress == true) { - /* lock the pages of the kernel buffer and translate them to pages */ - result = sep_lock_kernel_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array); - if (result) { - edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n"); - goto end_function; - } - } else { - /* lock the pages of the user buffer and translate them to pages */ - result = sep_lock_user_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array); - if (result) { - edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n"); - goto end_function; - } - } - - if (isKernelVirtualAddress == true) { - result = sep_lock_kernel_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array); - if (result) { - edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n"); - goto end_function_with_error1; - } - } else { - result = sep_lock_user_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array); - if (result) { - edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n"); - goto end_function_with_error1; - } - } - edbg("sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages); - edbg("sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages); - edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - - /* call the fucntion that creates table from the lli arrays */ - 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); - if (result) { - edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n"); - goto end_function_with_error2; - } - - /* fall through - free the lli entry arrays */ - dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr); - dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr); - dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr); -end_function_with_error2: - kfree(lli_out_array); -end_function_with_error1: - kfree(lli_in_array); -end_function: - dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result); - return result; - -} - - -/* This function creates the input and output dma tables for symmetric operations (AES/DES) according to the block size from LLI arays */ @@ -1196,629 +1331,412 @@ static int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_arra return 0; } -/* - this function calculates the size of data that can be inserted into the lli - table from this array the condition is that either the table is full - (all etnries are entered), or there are no more entries in the lli array -*/ -static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries) -{ - unsigned long table_data_size = 0; - unsigned long counter; - - /* calculate the data in the out lli table if till we fill the whole - table or till the data has ended */ - for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++) - table_data_size += lli_in_array_ptr[counter].block_size; - return table_data_size; -} /* - this functions builds ont lli table from the lli_array according to - the given size of data -*/ -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) -{ - unsigned long curr_table_data_size; - /* counter of lli array entry */ - unsigned long array_counter; - - dbg("SEP Driver:--------> sep_build_lli_table start\n"); - - /* init currrent table data size and lli array entry counter */ - curr_table_data_size = 0; - array_counter = 0; - *num_table_entries_ptr = 1; - - edbg("SEP Driver:table_data_size is %lu\n", table_data_size); - - /* fill the table till table size reaches the needed amount */ - while (curr_table_data_size < table_data_size) { - /* update the number of entries in table */ - (*num_table_entries_ptr)++; - - lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address; - lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size; - curr_table_data_size += lli_table_ptr->block_size; - - edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr); - edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - - /* check for overflow of the table data */ - if (curr_table_data_size > table_data_size) { - edbg("SEP Driver:curr_table_data_size > table_data_size\n"); - - /* update the size of block in the table */ - lli_table_ptr->block_size -= (curr_table_data_size - table_data_size); - - /* update the physical address in the lli array */ - lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size; - - /* update the block size left in the lli array */ - lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size); - } else - /* advance to the next entry in the lli_array */ - array_counter++; - - edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - - /* move to the next entry in table */ - lli_table_ptr++; - } - - /* set the info entry to default */ - lli_table_ptr->physical_address = 0xffffffff; - lli_table_ptr->block_size = 0; - - edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr); - edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - - /* set the output parameter */ - *num_processed_entries_ptr += array_counter; - - edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr); - dbg("SEP Driver:<-------- sep_build_lli_table end\n"); - return; -} - -/* - this function goes over the list of the print created tables and - prints all the data + This function builds input and output DMA tables for synhronic + symmetric operations (AES, DES). It also checks that each table + is of the modular block size */ -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) +static int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr, + unsigned long app_virt_out_addr, + unsigned long data_size, + 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, bool isKernelVirtualAddress) { - unsigned long table_count; - unsigned long entries_count; + /* array of pointers of page */ + struct sep_lli_entry_t *lli_in_array; + /* array of pointers of page */ + struct sep_lli_entry_t *lli_out_array; + int result = 0; - dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n"); + dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n"); - table_count = 1; - while ((unsigned long) lli_table_ptr != 0xffffffff) { - edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size); - edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries); + /* initialize the pages pointers */ + sep_dev->in_page_array = 0; + sep_dev->out_page_array = 0; - /* print entries of the table (without info entry) */ - for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) { - edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr); - edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size); + /* check if the pages are in Kernel Virtual Address layout */ + if (isKernelVirtualAddress == true) { + /* lock the pages of the kernel buffer and translate them to pages */ + result = sep_lock_kernel_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array); + if (result) { + edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n"); + goto end_function; + } + } else { + /* lock the pages of the user buffer and translate them to pages */ + result = sep_lock_user_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array); + if (result) { + edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n"); + goto end_function; } - - /* point to the info entry */ - lli_table_ptr--; - - edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - - - table_data_size = lli_table_ptr->block_size & 0xffffff; - num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff; - lli_table_ptr = (struct sep_lli_entry_t *) - (lli_table_ptr->physical_address); - - 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); - - if ((unsigned long) lli_table_ptr != 0xffffffff) - lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_area_phys_to_virt((unsigned long) lli_table_ptr); - - table_count++; - } - dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n"); -} - - -/* - This function locks all the physical pages of the application virtual buffer - and construct a basic lli array, where each entry holds the physical page - address and the size that application data holds in this physical pages -*/ -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) -{ - int error = 0; - /* the the page of the end address of the user space buffer */ - unsigned long end_page; - /* the page of the start address of the user space buffer */ - unsigned long start_page; - /* the range in pages */ - unsigned long num_pages; - struct page **page_array; - struct sep_lli_entry_t *lli_array; - unsigned long count; - int result; - - dbg("SEP Driver:--------> sep_lock_user_pages start\n"); - - /* set start and end pages and num pages */ - end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = app_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; - - edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr); - edbg("SEP Driver: data_size is %lu\n", data_size); - edbg("SEP Driver: start_page is %lu\n", start_page); - edbg("SEP Driver: end_page is %lu\n", end_page); - edbg("SEP Driver: num_pages is %lu\n", num_pages); - - /* allocate array of pages structure pointers */ - page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC); - if (!page_array) { - edbg("SEP Driver: kmalloc for page_array failed\n"); - - error = -ENOMEM; - goto end_function; } - lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC); - if (!lli_array) { - edbg("SEP Driver: kmalloc for lli_array failed\n"); - - error = -ENOMEM; - goto end_function_with_error1; + if (isKernelVirtualAddress == true) { + result = sep_lock_kernel_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array); + if (result) { + edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n"); + goto end_function_with_error1; + } + } else { + result = sep_lock_user_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array); + if (result) { + edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n"); + goto end_function_with_error1; + } } + edbg("sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages); + edbg("sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages); + edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - /* convert the application virtual address into a set of physical */ - down_read(¤t->mm->mmap_sem); - result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0); - up_read(¤t->mm->mmap_sem); - - /* check the number of pages locked - if not all then exit with error */ - if (result != num_pages) { - dbg("SEP Driver: not all pages locked by get_user_pages\n"); - error = -ENOMEM; + /* call the fucntion that creates table from the lli arrays */ + 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); + if (result) { + edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n"); goto end_function_with_error2; } - /* flush the cache */ - for (count = 0; count < num_pages; count++) - flush_dcache_page(page_array[count]); - - /* set the start address of the first page - app data may start not at - the beginning of the page */ - lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK)); - - /* check that not all the data is in the first page only */ - if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; - else - lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); - - /* debug print */ - 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); - - /* go from the second page to the prev before last */ - for (count = 1; count < (num_pages - 1); count++) { - lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]); - lli_array[count].block_size = PAGE_SIZE; - - 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); - } - - /* if more then 1 pages locked - then update for the last page size needed */ - if (num_pages > 1) { - /* update the address of the last page */ - lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]); - - /* set the size of the last page */ - lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK); - - if (lli_array[count].block_size == 0) { - dbg("app_virt_addr is %08lx\n", app_virt_addr); - dbg("data_size is %lu\n", data_size); - while (1); - } - 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); - } - - /* set output params */ - *lli_array_ptr = lli_array; - *num_pages_ptr = num_pages; - *page_array_ptr = page_array; - goto end_function; - + /* fall through - free the lli entry arrays */ + dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr); + dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr); + dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr); end_function_with_error2: - /* release the cache */ - for (count = 0; count < num_pages; count++) - page_cache_release(page_array[count]); - kfree(lli_array); + kfree(lli_out_array); end_function_with_error1: - kfree(page_array); + kfree(lli_in_array); end_function: - dbg("SEP Driver:<-------- sep_lock_user_pages end\n"); - return 0; + dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result); + return result; + } /* - This function locks all the physical pages of the kernel virtual buffer - and construct a basic lli array, where each entry holds the physical - page address and the size that application data holds in this physical pages + this function handles tha request for creation of the DMA table + for the synchronic symmetric operations (AES,DES) */ -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) +static int sep_create_sync_dma_tables_handler(unsigned long arg) { - int error = 0; - /* the the page of the end address of the user space buffer */ - unsigned long end_page; - /* the page of the start address of the user space buffer */ - unsigned long start_page; - /* the range in pages */ - unsigned long num_pages; - struct sep_lli_entry_t *lli_array; - /* next kernel address to map */ - unsigned long next_kernel_address; - unsigned long count; - - dbg("SEP Driver:--------> sep_lock_kernel_pages start\n"); - - /* set start and end pages and num pages */ - end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = kernel_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; + int error; + /* command arguments */ + struct sep_driver_build_sync_table_t command_args; - edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr); - edbg("SEP Driver: data_size is %lu\n", data_size); - edbg("SEP Driver: start_page is %lx\n", start_page); - edbg("SEP Driver: end_page is %lx\n", end_page); - edbg("SEP Driver: num_pages is %lu\n", num_pages); + dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n"); - lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC); - if (!lli_array) { - edbg("SEP Driver: kmalloc for lli_array failed\n"); - error = -ENOMEM; + error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t)); + if (error) goto end_function; - } - /* set the start address of the first page - app data may start not at - the beginning of the page */ - lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr); + edbg("app_in_address is %08lx\n", command_args.app_in_address); + edbg("app_out_address is %08lx\n", command_args.app_out_address); + edbg("data_size is %lu\n", command_args.data_in_size); + edbg("block_size is %lu\n", command_args.block_size); - /* check that not all the data is in the first page only */ - if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; + /* check if we need to build only input table or input/output */ + if (command_args.app_out_address) + /* prepare input and output tables */ + error = sep_prepare_input_output_dma_table(command_args.app_in_address, + command_args.app_out_address, + command_args.data_in_size, + command_args.block_size, + &command_args.in_table_address, + &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); else - lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK)); - - /* debug print */ - 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); - - /* advance the address to the start of the next page */ - next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE; - - /* go from the second page to the prev before last */ - for (count = 1; count < (num_pages - 1); count++) { - lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address); - lli_array[count].block_size = PAGE_SIZE; - - 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); - next_kernel_address += PAGE_SIZE; - } - - /* if more then 1 pages locked - then update for the last page size needed */ - if (num_pages > 1) { - /* update the address of the last page */ - lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address); - - /* set the size of the last page */ - lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK); - - if (lli_array[count].block_size == 0) { - dbg("app_virt_addr is %08lx\n", kernel_virt_addr); - dbg("data_size is %lu\n", data_size); - while (1); - } + /* prepare input tables */ + error = sep_prepare_input_dma_table(command_args.app_in_address, + 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); - 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); - } - /* set output params */ - *lli_array_ptr = lli_array; - *num_pages_ptr = num_pages; - *page_array_ptr = 0; + if (error) + goto end_function; + /* copy to user */ + error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t)); end_function: - dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n"); - return 0; + dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n"); + return error; } /* - This function releases all the application virtual buffer physical pages, - that were previously locked + this function handles the request for freeing dma table for synhronic actions */ -static int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag) +static int sep_free_dma_table_data_handler(void) { - unsigned long count; + dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n"); - if (dirtyFlag) { - for (count = 0; count < num_pages; count++) { - /* the out array was written, therefore the data was changed */ - if (!PageReserved(page_array_ptr[count])) - SetPageDirty(page_array_ptr[count]); - page_cache_release(page_array_ptr[count]); - } - } else { - /* free in pages - the data was only read, therefore no update was done - on those pages */ - for (count = 0; count < num_pages; count++) - page_cache_release(page_array_ptr[count]); - } + /* free input pages array */ + sep_free_dma_pages(sep_dev->in_page_array, sep_dev->in_num_pages, 0); - if (page_array_ptr) - /* free the array */ - kfree(page_array_ptr); + /* free output pages array if needed */ + if (sep_dev->out_page_array) + sep_free_dma_pages(sep_dev->out_page_array, sep_dev->out_num_pages, 1); + /* reset all the values */ + sep_dev->in_page_array = 0; + sep_dev->out_page_array = 0; + sep_dev->in_num_pages = 0; + sep_dev->out_num_pages = 0; + dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n"); return 0; } /* - This function raises interrupt to SEP that signals that is has a new - command from HOST + this function find a space for the new flow dma table */ -static void sep_send_command_handler(void) +static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr) { - unsigned long count; + int error = 0; + /* pointer to the id field of the flow dma table */ + unsigned long *start_table_ptr; + unsigned long flow_dma_area_start_addr; + unsigned long flow_dma_area_end_addr; + /* maximum table size in words */ + unsigned long table_size_in_words; - dbg("SEP Driver:--------> sep_send_command_handler start\n"); - sep_set_time(0, 0); + /* find the start address of the flow DMA table area */ + flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES; - /* flash cache */ - flush_cache_all(); + /* set end address of the flow table area */ + flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES; - for (count = 0; count < 12 * 4; count += 4) - edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count))); + /* set table size in words */ + table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2; - /* update counter */ - sep_dev->host_to_sep_send_counter++; - /* send interrupt to SEP */ - sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); - dbg("SEP Driver:<-------- sep_send_command_handler end\n"); - return; -} + /* set the pointer to the start address of DMA area */ + start_table_ptr = (unsigned long *) flow_dma_area_start_addr; -/* - This function raises interrupt to SEPm that signals that is has a - new command from HOST -*/ -static void sep_send_reply_command_handler(void) -{ - unsigned long count; + /* find the space for the next table */ + while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr)) + start_table_ptr += table_size_in_words; - dbg("SEP Driver:--------> sep_send_reply_command_handler start\n"); + /* check if we reached the end of floa tables area */ + if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr) + error = -1; + else + *table_address_ptr = start_table_ptr; - /* flash cache */ - flush_cache_all(); - for (count = 0; count < 12 * 4; count += 4) - edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count))); - /* update counter */ - sep_dev->host_to_sep_send_counter++; - /* send the interrupt to SEP */ - sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep_dev->host_to_sep_send_counter); - /* update both counters */ - sep_dev->host_to_sep_send_counter++; - sep_dev->sep_to_host_reply_counter++; - dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n"); + return error; } /* - This function handles the allocate data pool memory request - This function returns calculates the physical address of the - allocated memory, and the offset of this area from the mapped address. - Therefore, the FVOs in user space can calculate the exact virtual - address of this allocated memory + This function creates one DMA table for flow and returns its data, + and pointer to its info entry */ -static int sep_allocate_data_pool_memory_handler(unsigned long arg) +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) { int error; - struct sep_driver_alloc_t command_args; - - dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n"); + /* the range in pages */ + unsigned long lli_array_size; + struct sep_lli_entry_t *lli_array; + struct sep_lli_entry_t *flow_dma_table_entry_ptr; + unsigned long *start_dma_table_ptr; + /* total table data counter */ + unsigned long dma_table_data_count; + /* pointer that will keep the pointer to the pages of the virtual buffer */ + struct page **page_array_ptr; + unsigned long entry_count; - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t)); + /* find the space for the new table */ + error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr); if (error) goto end_function; - /* allocate memory */ - if ((sep_dev->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { - error = -ENOTTY; - goto end_function; - } - - /* set the virtual and physical address */ - command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated; - command_args.phys_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated; + /* check if the pages are in Kernel Virtual Address layout */ + if (isKernelVirtualAddress == true) + /* lock kernel buffer in the memory */ + error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr); + else + /* lock user buffer in the memory */ + error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr); - /* write the memory back to the user space */ - error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t)); if (error) goto end_function; - /* set the allocation */ - sep_dev->data_pool_bytes_allocated += command_args.num_bytes; + /* set the pointer to page array at the beginning of table - this table is + now considered taken */ + *start_dma_table_ptr = lli_array_size; -end_function: - dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n"); - return error; -} + /* point to the place of the pages pointers of the table */ + start_dma_table_ptr++; -/* - This function handles write into allocated data pool command -*/ -static int sep_write_into_data_pool_handler(unsigned long arg) -{ - int error; - unsigned long virt_address; - unsigned long app_in_address; - unsigned long num_bytes; - unsigned long data_pool_area_addr; + /* set the pages pointer */ + *start_dma_table_ptr = (unsigned long) page_array_ptr; - dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n"); + /* set the pointer to the first entry */ + flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr); - /* get the application address */ - error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address)); - if (error) - goto end_function; + /* now create the entries for table */ + for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) { + flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address; - /* get the virtual kernel address address */ - error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address)); - if (error) - goto end_function; + flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size; - /* get the number of bytes */ - error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes)); - if (error) - goto end_function; + /* set the total data of a table */ + dma_table_data_count += lli_array[entry_count].block_size; - /* calculate the start of the data pool */ - data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES; + flow_dma_table_entry_ptr++; + } + /* set the physical address */ + table_data->physical_address = virt_to_phys(start_dma_table_ptr); - /* check that the range of the virtual kernel address is correct */ - if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) { - error = -ENOTTY; - goto end_function; - } - /* copy the application data */ - error = copy_from_user((void *) virt_address, (void *) app_in_address, num_bytes); + /* set the num_entries and total data size */ + table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count); + + /* set the info entry */ + flow_dma_table_entry_ptr->physical_address = 0xffffffff; + flow_dma_table_entry_ptr->block_size = 0; + + /* set the pointer to info entry */ + *info_entry_ptr = flow_dma_table_entry_ptr; + + /* the array of the lli entries */ + kfree(lli_array); end_function: - dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n"); return error; } + + /* - this function handles the read from data pool command + This function creates a list of tables for flow and returns the data for + the first and last tables of the list */ -static int sep_read_from_data_pool_handler(unsigned long arg) +static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers, + 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) { int error; - /* virtual address of dest application buffer */ - unsigned long app_out_address; - /* virtual address of the data pool */ - unsigned long virt_address; - unsigned long num_bytes; - unsigned long data_pool_area_addr; + 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_lli_entry_t *prev_info_entry_ptr; + unsigned long i; - dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n"); + /* init vars */ + error = 0; + prev_info_entry_ptr = 0; - /* get the application address */ - error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address)); - if (error) - goto end_function; + /* init the first table to default */ + table_data.physical_address = 0xffffffff; + first_table_data_ptr->physical_address = 0xffffffff; + table_data.block_size = 0; - /* get the virtual kernel address address */ - error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address)); - if (error) - goto end_function; + for (i = 0; i < num_virtual_buffers; i++) { + /* get the virtual buffer address */ + error = get_user(virt_buff_addr, &first_buff_addr); + if (error) + goto end_function; - /* get the number of bytes */ - error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes)); - if (error) - goto end_function; + /* get the virtual buffer size */ + first_buff_addr++; + error = get_user(virt_buff_size, &first_buff_addr); + if (error) + goto end_function; - /* calculate the start of the data pool */ - data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES; + /* advance the address to point to the next pair of address|size */ + first_buff_addr++; - /* check that the range of the virtual kernel address is correct */ - if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) { - error = -ENOTTY; - goto end_function; + /* now prepare the one flow LLI table from the data */ + error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress); + if (error) + goto end_function; + + if (i == 0) { + /* if this is the first table - save it to return to the user + application */ + *first_table_data_ptr = table_data; + + /* set the pointer to info entry */ + prev_info_entry_ptr = info_entry_ptr; + } else { + /* not first table - the previous table info entry should + be updated */ + prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size); + + /* set the pointer to info entry */ + prev_info_entry_ptr = info_entry_ptr; + } } - /* copy the application data */ - error = copy_to_user((void *) app_out_address, (void *) virt_address, num_bytes); + /* set the last table data */ + *last_table_data_ptr = table_data; end_function: - dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n"); return error; } - /* - this function handles tha request for creation of the DMA table - for the synchronic symmetric operations (AES,DES) + this function goes over all the flow tables connected to the given + table and deallocate them */ -static int sep_create_sync_dma_tables_handler(unsigned long arg) +static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr) { - int error; - /* command arguments */ - struct sep_driver_build_sync_table_t command_args; + /* id pointer */ + unsigned long *table_ptr; + /* end address of the flow dma area */ + unsigned long num_entries; + unsigned long num_pages; + struct page **pages_ptr; + /* maximum table size in words */ + struct sep_lli_entry_t *info_entry_ptr; - dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n"); + /* set the pointer to the first table */ + table_ptr = (unsigned long *) first_table_ptr->physical_address; - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t)); - if (error) - goto end_function; + /* set the num of entries */ + num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) + & SEP_NUM_ENTRIES_MASK; - edbg("app_in_address is %08lx\n", command_args.app_in_address); - edbg("app_out_address is %08lx\n", command_args.app_out_address); - edbg("data_size is %lu\n", command_args.data_in_size); - edbg("block_size is %lu\n", command_args.block_size); + /* go over all the connected tables */ + while (*table_ptr != 0xffffffff) { + /* get number of pages */ + num_pages = *(table_ptr - 2); - /* check if we need to build only input table or input/output */ - if (command_args.app_out_address) - /* prepare input and output tables */ - error = sep_prepare_input_output_dma_table(command_args.app_in_address, - command_args.app_out_address, - command_args.data_in_size, - command_args.block_size, - &command_args.in_table_address, - &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); - else - /* prepare input tables */ - error = sep_prepare_input_dma_table(command_args.app_in_address, - 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); + /* get the pointer to the pages */ + pages_ptr = (struct page **) (*(table_ptr - 1)); - if (error) - goto end_function; - /* copy to user */ - error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t)); -end_function: - dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n"); - return error; + /* free the pages */ + sep_free_dma_pages(pages_ptr, num_pages, 1); + + /* goto to the info entry */ + info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1); + + table_ptr = (unsigned long *) info_entry_ptr->physical_address; + num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK; + } + + return; } /* - this function handles the request for freeing dma table for synhronic actions + This function returns pointer to the flow data structure + that contains the given id */ -static int sep_free_dma_table_data_handler(void) +static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr) { - dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n"); + unsigned long count; + int error = 0; - /* free input pages array */ - sep_free_dma_pages(sep_dev->in_page_array, sep_dev->in_num_pages, 0); + /* + always search for flow with id default first - in case we + already started working on the flow there can be no situation + when 2 flows are with default flag + */ + for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) { + if (sep_dev->flows_data_array[count].flow_id == flow_id) { + *flow_data_ptr = &sep_dev->flows_data_array[count]; + break; + } + } - /* free output pages array if needed */ - if (sep_dev->out_page_array) - sep_free_dma_pages(sep_dev->out_page_array, sep_dev->out_num_pages, 1); + if (count == SEP_DRIVER_NUM_FLOWS) + /* no flow found */ + error = -ENOMEM; - /* reset all the values */ - sep_dev->in_page_array = 0; - sep_dev->out_page_array = 0; - sep_dev->in_num_pages = 0; - sep_dev->out_num_pages = 0; - dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n"); - return 0; + return error; } + /* this function handles the request to create the DMA tables for flow */ @@ -2275,328 +2193,223 @@ static int sep_end_transaction_handler(unsigned long arg) } - /* - This function creates a list of tables for flow and returns the data for - the first and last tables of the list + This function handler the set flow id command */ -static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers, - 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) +static int sep_set_flow_id_handler(unsigned long arg) { int error; - 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_lli_entry_t *prev_info_entry_ptr; - unsigned long i; - - /* init vars */ - error = 0; - prev_info_entry_ptr = 0; - - /* init the first table to default */ - table_data.physical_address = 0xffffffff; - first_table_data_ptr->physical_address = 0xffffffff; - table_data.block_size = 0; - - for (i = 0; i < num_virtual_buffers; i++) { - /* get the virtual buffer address */ - error = get_user(virt_buff_addr, &first_buff_addr); - if (error) - goto end_function; - - /* get the virtual buffer size */ - first_buff_addr++; - error = get_user(virt_buff_size, &first_buff_addr); - if (error) - goto end_function; - - /* advance the address to point to the next pair of address|size */ - first_buff_addr++; - - /* now prepare the one flow LLI table from the data */ - error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress); - if (error) - goto end_function; - - if (i == 0) { - /* if this is the first table - save it to return to the user - application */ - *first_table_data_ptr = table_data; - - /* set the pointer to info entry */ - prev_info_entry_ptr = info_entry_ptr; - } else { - /* not first table - the previous table info entry should - be updated */ - prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size); - - /* set the pointer to info entry */ - prev_info_entry_ptr = info_entry_ptr; - } - } - - /* set the last table data */ - *last_table_data_ptr = table_data; -end_function: - return error; -} - + unsigned long flow_id; + struct sep_flow_context_t *flow_data_ptr; -/* - This function creates one DMA table for flow and returns its data, - and pointer to its info entry -*/ -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) -{ - int error; - /* the range in pages */ - unsigned long lli_array_size; - struct sep_lli_entry_t *lli_array; - struct sep_lli_entry_t *flow_dma_table_entry_ptr; - unsigned long *start_dma_table_ptr; - /* total table data counter */ - unsigned long dma_table_data_count; - /* pointer that will keep the pointer to the pages of the virtual buffer */ - struct page **page_array_ptr; - unsigned long entry_count; + dbg("------------>SEP Driver: sep_set_flow_id_handler start\n"); - /* find the space for the new table */ - error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr); + error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id)); if (error) goto end_function; - /* check if the pages are in Kernel Virtual Address layout */ - if (isKernelVirtualAddress == true) - /* lock kernel buffer in the memory */ - error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr); - else - /* lock user buffer in the memory */ - error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr); - + /* find the flow data structure that was just used for creating new flow + - its id should be default */ + error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr); if (error) goto end_function; - /* set the pointer to page array at the beginning of table - this table is - now considered taken */ - *start_dma_table_ptr = lli_array_size; - - /* point to the place of the pages pointers of the table */ - start_dma_table_ptr++; - - /* set the pages pointer */ - *start_dma_table_ptr = (unsigned long) page_array_ptr; - - /* set the pointer to the first entry */ - flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr); - - /* now create the entries for table */ - for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) { - flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address; - - flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size; - - /* set the total data of a table */ - dma_table_data_count += lli_array[entry_count].block_size; - - flow_dma_table_entry_ptr++; - } - - /* set the physical address */ - table_data->physical_address = virt_to_phys(start_dma_table_ptr); - - /* set the num_entries and total data size */ - table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count); - - /* set the info entry */ - flow_dma_table_entry_ptr->physical_address = 0xffffffff; - flow_dma_table_entry_ptr->block_size = 0; - - /* set the pointer to info entry */ - *info_entry_ptr = flow_dma_table_entry_ptr; + /* set flow id */ + flow_data_ptr->flow_id = flow_id; - /* the array of the lli entries */ - kfree(lli_array); end_function: + dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n"); return error; } -/* - This function returns pointer to the flow data structure - that contains the given id -*/ -static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr) -{ - unsigned long count; - int error = 0; - - /* - always search for flow with id default first - in case we - already started working on the flow there can be no situation - when 2 flows are with default flag - */ - for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) { - if (sep_dev->flows_data_array[count].flow_id == flow_id) { - *flow_data_ptr = &sep_dev->flows_data_array[count]; - break; - } - } - if (count == SEP_DRIVER_NUM_FLOWS) - /* no flow found */ - error = -ENOMEM; - return error; -} -/* - this function find a space for the new flow dma table -*/ -static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr) +static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int error = 0; - /* pointer to the id field of the flow dma table */ - unsigned long *start_table_ptr; - unsigned long flow_dma_area_start_addr; - unsigned long flow_dma_area_end_addr; - /* maximum table size in words */ - unsigned long table_size_in_words; - /* find the start address of the flow DMA table area */ - flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES; + dbg("------------>SEP Driver: ioctl start\n"); - /* set end address of the flow table area */ - flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES; + edbg("SEP Driver: cmd is %x\n", cmd); - /* set table size in words */ - table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2; + /* check that the command is for sep device */ + if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) + error = -ENOTTY; - /* set the pointer to the start address of DMA area */ - start_table_ptr = (unsigned long *) flow_dma_area_start_addr; + switch (cmd) { + case SEP_IOCSENDSEPCOMMAND: + /* send command to SEP */ + sep_send_command_handler(); + edbg("SEP Driver: after sep_send_command_handler\n"); + break; + case SEP_IOCSENDSEPRPLYCOMMAND: + /* send reply command to SEP */ + sep_send_reply_command_handler(); + break; + case SEP_IOCALLOCDATAPOLL: + /* allocate data pool */ + error = sep_allocate_data_pool_memory_handler(arg); + break; + case SEP_IOCWRITEDATAPOLL: + /* write data into memory pool */ + error = sep_write_into_data_pool_handler(arg); + break; + case SEP_IOCREADDATAPOLL: + /* read data from data pool into application memory */ + error = sep_read_from_data_pool_handler(arg); + break; + case SEP_IOCCREATESYMDMATABLE: + /* create dma table for synhronic operation */ + error = sep_create_sync_dma_tables_handler(arg); + break; + case SEP_IOCCREATEFLOWDMATABLE: + /* create flow dma tables */ + error = sep_create_flow_dma_tables_handler(arg); + break; + case SEP_IOCFREEDMATABLEDATA: + /* free the pages */ + error = sep_free_dma_table_data_handler(); + break; + case SEP_IOCSETFLOWID: + /* set flow id */ + error = sep_set_flow_id_handler(arg); + break; + case SEP_IOCADDFLOWTABLE: + /* add tables to the dynamic flow */ + error = sep_add_flow_tables_handler(arg); + break; + case SEP_IOCADDFLOWMESSAGE: + /* add message of add tables to flow */ + error = sep_add_flow_tables_message_handler(arg); + break; + case SEP_IOCSEPSTART: + /* start command to sep */ + error = sep_start_handler(); + break; + case SEP_IOCSEPINIT: + /* init command to sep */ + error = sep_init_handler(arg); + break; + case SEP_IOCSETAPIMODE: + /* set non- blocking mode */ + error = sep_set_api_mode_handler(arg); + break; + case SEP_IOCGETSTATICPOOLADDR: + /* get the physical and virtual addresses of the static pool */ + error = sep_get_static_pool_addr_handler(arg); + break; + case SEP_IOCENDTRANSACTION: + error = sep_end_transaction_handler(arg); + break; + case SEP_IOCREALLOCCACHERES: + error = sep_realloc_cache_resident_handler(arg); + break; + case SEP_IOCGETMAPPEDADDROFFSET: + error = sep_get_physical_mapped_offset_handler(arg); + break; + case SEP_IOCGETIME: + error = sep_get_time_handler(arg); + break; + default: + error = -ENOTTY; + break; + } + dbg("SEP Driver:<-------- ioctl end\n"); + return error; +} - /* find the space for the next table */ - while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr)) - start_table_ptr += table_size_in_words; - /* check if we reached the end of floa tables area */ - if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr) - error = -1; - else - *table_address_ptr = start_table_ptr; - return error; -} +#if !SEP_DRIVER_POLLING_MODE -/* - this function goes over all the flow tables connected to the given - table and deallocate them -*/ -static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr) -{ - /* id pointer */ - unsigned long *table_ptr; - /* end address of the flow dma area */ - unsigned long num_entries; - unsigned long num_pages; - struct page **pages_ptr; - /* maximum table size in words */ - struct sep_lli_entry_t *info_entry_ptr; +/* handler for flow done interrupt */ - /* set the pointer to the first table */ - table_ptr = (unsigned long *) first_table_ptr->physical_address; +static void sep_flow_done_handler(struct work_struct *work) +{ + struct sep_flow_context_t *flow_data_ptr; - /* set the num of entries */ - num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) - & SEP_NUM_ENTRIES_MASK; + /* obtain the mutex */ + mutex_lock(&sep_mutex); - /* go over all the connected tables */ - while (*table_ptr != 0xffffffff) { - /* get number of pages */ - num_pages = *(table_ptr - 2); + /* get the pointer to context */ + flow_data_ptr = (struct sep_flow_context_t *) work; - /* get the pointer to the pages */ - pages_ptr = (struct page **) (*(table_ptr - 1)); + /* free all the current input tables in sep */ + sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process); - /* free the pages */ - sep_free_dma_pages(pages_ptr, num_pages, 1); + /* free all the current tables output tables in SEP (if needed) */ + if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff) + sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process); - /* goto to the info entry */ - info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1); + /* check if we have additional tables to be sent to SEP only input + flag may be checked */ + if (flow_data_ptr->input_tables_flag) { + /* copy the message to the shared RAM and signal SEP */ + memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes); - table_ptr = (unsigned long *) info_entry_ptr->physical_address; - num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK; + sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2); } - - return; + mutex_unlock(&sep_mutex); } - /* - This function handler the set flow id command + interrupt handler function */ -static int sep_set_flow_id_handler(unsigned long arg) +static irqreturn_t sep_inthandler(int irq, void *dev_id) { - int error; + irqreturn_t int_error; + unsigned long error; + unsigned long reg_val; unsigned long flow_id; - struct sep_flow_context_t *flow_data_ptr; - - dbg("------------>SEP Driver: sep_set_flow_id_handler start\n"); - - error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id)); - if (error) - goto end_function; - - /* find the flow data structure that was just used for creating new flow - - its id should be default */ - error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr); - if (error) - goto end_function; - - /* set flow id */ - flow_data_ptr->flow_id = flow_id; + struct sep_flow_context_t *flow_context_ptr; -end_function: - dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n"); - return error; -} + int_error = IRQ_HANDLED; + /* read the IRR register to check if this is SEP interrupt */ + reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR); + edbg("SEP Interrupt - reg is %08lx\n", reg_val); -/* - calculates time and sets it at the predefined address -*/ -static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr) -{ - struct timeval time; - /* address of time in the kernel */ - unsigned long time_addr; + /* check if this is the flow interrupt */ + if (0 /*reg_val & (0x1 << 11) */ ) { + /* read GPRO to find out the which flow is done */ + flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR); + /* find the contex of the flow */ + error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr); + if (error) + goto end_function_with_error; - dbg("SEP Driver:--------> sep_set_time start\n"); + INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler); - do_gettimeofday(&time); + /* queue the work */ + queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq); - /* set value in the SYSTEM MEMORY offset */ - time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES; + } else { + /* check if this is reply interrupt from SEP */ + if (reg_val & (0x1 << 13)) { + /* update the counter of reply messages */ + sep_dev->sep_to_host_reply_counter++; - *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN; - *(unsigned long *) (time_addr + 4) = time.tv_sec; + /* wake up the waiting process */ + wake_up(&g_sep_event); + } else { + int_error = IRQ_NONE; + goto end_function; + } + } +end_function_with_error: + /* clear the interrupt */ + sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val); +end_function: + return int_error; +} - edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec); - edbg("SEP Driver:time_addr is %lu\n", time_addr); - edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr); +#endif - /* set the output parameters if needed */ - if (address_ptr) - *address_ptr = sep_shared_area_virt_to_phys(time_addr); - if (time_in_sec_ptr) - *time_in_sec_ptr = time.tv_sec; - dbg("SEP Driver:<-------- sep_set_time end\n"); - return 0; -} static void sep_wait_busy(struct sep_device *dev) { diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h index 4df2698..c9f4e56 100644 --- a/drivers/staging/sep/sep_driver_api.h +++ b/drivers/staging/sep/sep_driver_api.h @@ -451,46 +451,4 @@ struct sep_flow_context_t { }; -/* - This function releases all the application virtual - buffer physical pages, that were previously locked -*/ -static int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag); - -/* - This function creates the input and output dma tables for - symmetric operations (AES/DES) according to the block size - from LLI arays -*/ -static int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array, - unsigned long sep_in_lli_entries, - struct sep_lli_entry_t *lli_out_array, - unsigned long sep_out_lli_entries, - 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); - -/* - This function builds input and output DMA tables for synhronic symmetric - operations (AES, DES) It also checks that each table is of the modular - block size -*/ -static int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr, - unsigned long app_virt_out_addr, - unsigned long data_size, - 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, bool isKernelVirtualAddress); - -/* - This function prepares only input DMA table for synhronic symmetric - operations (HASH) -*/ -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); - - -/* - this function handles the request for freeing dma table for - synhronic actions -*/ -static int sep_free_dma_table_data_handler(void); - - #endif diff --git a/drivers/staging/sep/sep_driver_ext_api.h b/drivers/staging/sep/sep_driver_ext_api.h deleted file mode 100644 index cad9057..0000000 --- a/drivers/staging/sep/sep_driver_ext_api.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * sep_driver_ext_api.h - Security Processor Driver external api definitions - * - * Copyright(c) 2009 Intel Corporation. All rights reserved. - * Copyright(c) 2009 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * - */ - -#ifndef __SEP_DRIVER_EXT_API_H__ -#define __SEP_DRIVER_EXT_API_H__ - - -/* shared variables */ -static int sepDebug; - -/* -this function loads the ROM code in SEP (needed only in the debug mode on FPGA) -*/ -static void sep_load_rom_code(void); - -/* -This functions copies the cache and resident from their source location into -destination memory, which is external to Linux VM and is given as physical -address -*/ -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); - -/* -This functions maps and allocates the shared area on the external -RAM (device) The input is shared_area_size - the size of the memory -to allocate. The outputs are kernel_shared_area_addr_ptr - the kerenl -address of the mapped and allocated shared area, and -phys_shared_area_addr_ptr - the physical address of the shared area -*/ -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); - -/* -This functions unmaps and deallocates the shared area on the external -RAM (device) The input is shared_area_size - the size of the memory to -deallocate,kernel_shared_area_addr_ptr - the kernel address of the -mapped and allocated shared area,phys_shared_area_addr_ptr - the physical -address of the shared area -*/ -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); - - -/* -This functions returns the physical address inside shared area according -to the virtual address. It can be either on the externa RAM device -(ioremapped), or on the system RAM -*/ -static unsigned long sep_shared_area_virt_to_phys(unsigned long virt_address); - -/* -This functions returns the vitrual address inside shared area according -to the physical address. It can be either on the externa RAM device -(ioremapped), or on the system RAM This implementation is for the external RAM -*/ -static unsigned long sep_shared_area_phys_to_virt(unsigned long phys_address); - -#endif /*__SEP_DRIVER_EXT_API_H__*/ |