aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2010-12-08 10:57:26 +0000
committerAlan Cox <alan@linux.intel.com>2010-12-08 10:57:26 +0000
commit8b137d1a0a5da49c202c46bb9063aa38857724a2 (patch)
treebe958864acb10c926c78fbf43266c92ceebbaa13
parenta8be9bd09e432236c10c70a78c3043a51f082f0c (diff)
downloadmrst-s0i3-test-8b137d1a0a5da49c202c46bb9063aa38857724a2.tar.gz
mrst-s0i3-test-8b137d1a0a5da49c202c46bb9063aa38857724a2.tar.xz
mrst-s0i3-test-8b137d1a0a5da49c202c46bb9063aa38857724a2.zip
Signed-off-by: Mark A. Allyn <mark.a.allyn@intel.com>
-rw-r--r--drivers/staging/sep/sep_driver.c1377
1 files changed, 1089 insertions, 288 deletions
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 981d90480c4..5f73add54c9 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -1710,591 +1710,1392 @@ end_function:
}
/*
- 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
+ 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
+ @sep: pointer to struct sep_device
+ @lli_in_array_ptr
+ @num_array_entries
+ @last_table_flag
*/
-static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries)
+static u32 sep_calculate_lli_table_max_size(struct sep_device *sep,
+ struct sep_lli_entry_t *lli_in_array_ptr,
+ u32 num_array_entries,
+ u32 *last_table_flag)
{
- unsigned long table_data_size = 0;
- unsigned long counter;
+ /* table data size */
+ u32 table_data_size;
+
+ /* data size for the next table */
+ u32 next_table_data_size;
+
+ /* counter */
+ u32 counter;
+
+ /*---------------------
+ CODE
+ ----------------------*/
+
+ table_data_size = 0;
+ *last_table_flag = 0;
- /* 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++)
+ /* calculate the data in the out lli table 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;
+
+ /* check if we reached the last entry,
+ meaning this ia the last table to build,
+ and no need to check the block alignment */
+ if (counter == num_array_entries) {
+
+ /* set the last table flag */
+ *last_table_flag = 1;
+ goto end_function;
+ }
+
+ /* calculate the data size of the next table. Stop if no entries left or
+ if data size is more the DMA restriction
+ */
+ next_table_data_size = 0;
+ for (; counter < num_array_entries; counter++) {
+
+ next_table_data_size += lli_in_array_ptr[counter].block_size;
+
+ if (next_table_data_size >= SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE)
+
+ break;
+ }
+
+ /* check if the next table data size is less then DMA rstriction.
+ if it is - recalculate the current table size, so that the next
+ table data size will be adaquete for DMA
+ */
+ if (next_table_data_size &&
+ next_table_data_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE)
+
+ table_data_size -= (SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE -
+ next_table_data_size);
+
+ dev_dbg(&sep->pdev->dev,
+ "table data size is %x\n", table_data_size);
+
+end_function:
+
return table_data_size;
}
/*
this functions builds ont lli table from the lli_array according to
the given size of data
+ @sep: pointer to struct sep_device
+ @lli_array_ptr: pointer to lli array
+ @lli_table_ptr: pointer to lli table
+ @num_processed_entries_ptr: pointer to number of entries
+ @num_table_entries_ptr: pointer to number of tables
+ @table_data_size: total data size
*/
-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)
+static void sep_build_lli_table(struct sep_device *sep,
+ struct sep_lli_entry_t *lli_array_ptr,
+ struct sep_lli_entry_t *lli_table_ptr,
+ u32 *num_processed_entries_ptr,
+ u32 *num_table_entries_ptr,
+ u32 table_data_size)
{
- unsigned long curr_table_data_size;
+ /* current table data size */
+ u32 curr_table_data_size;
+
/* counter of lli array entry */
- unsigned long array_counter;
+ u32 array_counter;
- dbg("SEP Driver:--------> sep_build_lli_table start\n");
+ /*-----------------------
+ CODE
+ ---------------------------*/
+
+ dev_dbg(&sep->pdev->dev,
+ "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);
+ dev_dbg(&sep->pdev->dev,
+ "table_data_size is %x\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;
+ lli_table_ptr->bus_address =
+ cpu_to_le32(lli_array_ptr[array_counter].bus_address);
+
+ lli_table_ptr->block_size =
+ cpu_to_le32(lli_array_ptr[array_counter].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);
+ curr_table_data_size += lli_array_ptr[array_counter].block_size;
+
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr is %08x\n", (u32)lli_table_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr->bus_address is %08x\n",
+ lli_table_ptr->bus_address);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr->block_size is %x\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");
+
+ dev_dbg(&sep->pdev->dev,
+ "curr_table_data_size too large\n");
/* update the size of block in the table */
- lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
+ lli_table_ptr->block_size -=
+ cpu_to_le32((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;
+ lli_array_ptr[array_counter].bus_address +=
+ cpu_to_le32(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);
+ 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);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr->bus_address is %08x\n",
+ lli_table_ptr->bus_address);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr->block_size is %x\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->bus_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);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr is %08x\n", (u32)lli_table_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr->bus_address is %08x\n",
+ lli_table_ptr->bus_address);
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr->block_size is %x\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");
+ dev_dbg(&sep->pdev->dev,
+ "num_processed_entries_ptr is %x\n",
+ *num_processed_entries_ptr);
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_build_lli_table end\n");
+
return;
}
/*
+ 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
+ This implementation is for the external RAM
+*/
+static dma_addr_t sep_shared_area_virt_to_bus(struct sep_device *sep,
+ void *virt_address)
+{
+ dev_dbg(&sep->pdev->dev,
+ "sh virt to phys v %08lx\n",
+ (unsigned long)virt_address);
+ dev_dbg(&sep->pdev->dev,
+ "sh virt to phys p %08lx\n",
+ (unsigned long)(sep->shared_bus
+ + (virt_address - sep->shared_addr)));
+
+ return sep->shared_bus
+ + (size_t)(virt_address - sep->shared_addr);
+}
+
+/*
+ This functions returns the virtual 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 void *sep_shared_area_bus_to_virt(struct sep_device *sep,
+ dma_addr_t bus_address)
+{
+ dev_dbg(&sep->pdev->dev,
+ "shared bus to virt b=%x v=%x\n",
+ (u32)bus_address,
+ (u32)(sep->shared_addr +
+ (size_t)(bus_address - sep->shared_bus)));
+
+ return sep->shared_addr
+ + (size_t)(bus_address - sep->shared_bus);
+}
+
+/*
this function goes over the list of the print created tables and
prints all the data
+ @sep: pointer to struct sep_device
+ @lli_table_ptr: pointer to sep_lli_entry_t
+ @num_table_entries: number of entries
+ @table_data_size: total data size
*/
-static void sep_debug_print_lli_tables(struct sep_device *sep, struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size)
+static void sep_debug_print_lli_tables(struct sep_device *sep,
+ 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;
+ unsigned long table_count = 0;
+ unsigned long entries_count = 0;
- dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
+ dev_dbg(&sep->pdev->dev,
+ "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);
+ dev_dbg(&sep->pdev->dev,
+ "lli table %08lx, table_data_size is %lu\n",
+ table_count, table_data_size);
+ dev_dbg(&sep->pdev->dev,
+ "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);
+ for (entries_count = 0; entries_count < num_table_entries;
+ entries_count++, lli_table_ptr++) {
+
+ dev_dbg(&sep->pdev->dev,
+ "lli_table_ptr address is %08lx\n",
+ (unsigned long) lli_table_ptr);
+
+ dev_dbg(&sep->pdev->dev,
+ "phys address is %08lx block size is %x\n",
+ (unsigned long)lli_table_ptr->bus_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);
+ dev_dbg(&sep->pdev->dev,
+ "phys lli_table_ptr->block_size is %x\n",
+ lli_table_ptr->block_size);
+
+ dev_dbg(&sep->pdev->dev,
+ "phys lli_table_ptr->physical_address is %08lu\n",
+ (unsigned long)lli_table_ptr->bus_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);
+ (lli_table_ptr->bus_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);
+ dev_dbg(&sep->pdev->dev,
+ "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_bus_to_virt(sep, (unsigned long) lli_table_ptr);
+ if ((unsigned long)lli_table_ptr != 0xffffffff)
+ lli_table_ptr = (struct sep_lli_entry_t *)
+ sep_shared_bus_to_virt(sep,
+ (unsigned long)lli_table_ptr);
table_count++;
}
- dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
+ dev_dbg(&sep->pdev->dev,
+ "sep_debug_print_lli_tables end\n");
}
/*
- This function prepares only input DMA table for synhronic symmetric
- operations (HASH)
+ This function creates empty lli tables when there is no data
+ @sep: pointer to struct sep_device
+ @lli_table_addr_ptr: pointer to lli table
+ @num_entries_ptr: pointer to number of entries
+ @table_data_size_ptr: point to table data size
+*/
+static void sep_prepare_empty_lli_table(struct sep_device *sep,
+ dma_addr_t *lli_table_addr_ptr,
+ u32 *num_entries_ptr,
+ u32 *table_data_size_ptr)
+{
+ /* lli table pointer */
+ struct sep_lli_entry_t *lli_table_ptr;
+
+ /*---------------------
+ CODE
+ ------------------------*/
+
+ dev_dbg(&sep->pdev->dev, "sep_prepare_empty_lli_table start\n");
+
+ /* find the area for new table */
+ lli_table_ptr =
+ (struct sep_lli_entry_t *)(sep->shared_addr +
+ SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
+ sep->num_lli_tables_created *
+ sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
+
+ lli_table_ptr->bus_address = 0;
+ lli_table_ptr->block_size = 0;
+
+ lli_table_ptr++;
+ lli_table_ptr->bus_address = 0xFFFFFFFF;
+ lli_table_ptr->block_size = 0;
+
+ /* set the output parameter value */
+ *lli_table_addr_ptr = sep->shared_bus +
+ SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
+ sep->num_lli_tables_created *
+ sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+
+ /* set the num of entries and table data size for empty table */
+ *num_entries_ptr = 2;
+ *table_data_size_ptr = 0;
+
+ /* update the number of created tables */
+ sep->num_lli_tables_created++;
+
+ dev_dbg(&sep->pdev->dev, "sep_prepare_empty_lli_table start\n");
+
+}
+
+/*
+ This function prepares only input DMA table for synhronic symmetric
+ operations (HASH)
*/
static int sep_prepare_input_dma_table(struct sep_device *sep,
- 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)
+ unsigned long app_virt_addr,
+ u32 data_size,
+ u32 block_size,
+ dma_addr_t *lli_table_ptr,
+ u32 *num_entries_ptr,
+ u32 *table_data_size_ptr,
+ bool isKernelVirtualAddress)
+
{
/* pointer to the info entry of the table - the last entry */
struct sep_lli_entry_t *info_entry_ptr;
+
/* array of pointers ot page */
struct sep_lli_entry_t *lli_array_ptr;
+
/* points to the first entry to be processed in the lli_in_array */
- unsigned long current_entry;
+ u32 current_entry = 0;
+
/* num entries in the virtual buffer */
- unsigned long sep_lli_entries;
+ u32 sep_lli_entries = 0;
+
/* lli table pointer */
struct sep_lli_entry_t *in_lli_table_ptr;
+
/* the total data in one table */
- unsigned long table_data_size;
+ u32 table_data_size = 0;
+
+ /* flag for last table */
+ u32 last_table_flag = 0;
+
/* number of entries in lli table */
- unsigned long num_entries_in_table;
+ u32 num_entries_in_table = 0;
+
/* next table address */
- void *lli_table_alloc_addr;
- unsigned long result;
+ u32 lli_table_alloc_addr = 0;
- dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
+ /* error */
+ int error = 0;
- edbg("SEP Driver:data_size is %lu\n", data_size);
- edbg("SEP Driver:block_size is %lu\n", block_size);
+ /*------------------------
+ CODE
+ --------------------------*/
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_prepare_input_dma_table start\n");
+
+ dev_dbg(&sep->pdev->dev,
+ "data_size is %x\n", data_size);
+ dev_dbg(&sep->pdev->dev,
+ "block_size is %x\n", block_size);
/* initialize the pages pointers */
- sep->in_page_array = 0;
- sep->in_num_pages = 0;
+ sep->dma_res_arr[sep->nr_dcb_creat].in_page_array = 0;
+ sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages = 0;
- if (data_size == 0) {
- /* special case - created 2 entries table with zero data */
- in_lli_table_ptr = (struct sep_lli_entry_t *) (sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
- /* FIXME: Should the entry below not be for _bus */
- in_lli_table_ptr->physical_address = (unsigned long)sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
- in_lli_table_ptr->block_size = 0;
+ /* set the kernel address for first table to be allocated */
+ lli_table_alloc_addr = (u32)(sep->shared_addr +
+ SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
+ sep->num_lli_tables_created *
+ sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
- in_lli_table_ptr++;
- in_lli_table_ptr->physical_address = 0xFFFFFFFF;
- in_lli_table_ptr->block_size = 0;
+ if (data_size == 0) {
- *lli_table_ptr = sep->shared_bus + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
- *num_entries_ptr = 2;
- *table_data_size_ptr = 0;
+ /* special case - create meptu table - 2 entries, zero data */
+ sep_prepare_empty_lli_table(sep, lli_table_ptr,
+ num_entries_ptr,
+ table_data_size_ptr);
- goto end_function;
+ goto update_dcb_counter;
}
/* 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(sep, app_virt_addr, data_size, &sep->in_num_pages, &lli_array_ptr, &sep->in_page_array);
+
+ /* lock the pages of the kernel
+ buffer and translate them to pages */
+ error = sep_lock_kernel_pages(sep, app_virt_addr,
+ data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG);
else
- /* lock the pages of the user buffer and translate them to pages */
- result = sep_lock_user_pages(sep, app_virt_addr, data_size, &sep->in_num_pages, &lli_array_ptr, &sep->in_page_array);
- if (result)
- return result;
+ /* lock the pages of the user buffer
+ and translate them to pages */
+ error = sep_lock_user_pages(sep, app_virt_addr,
+ data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG);
- edbg("SEP Driver:output sep->in_num_pages is %lu\n", sep->in_num_pages);
+ if (error)
+ goto end_function;
+
+ dev_dbg(&sep->pdev->dev,
+ "output sep_in_num_pages is %x\n",
+ sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages);
current_entry = 0;
info_entry_ptr = 0;
- sep_lli_entries = sep->in_num_pages;
- /* initiate to point after the message area */
- lli_table_alloc_addr = sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+ sep_lli_entries =
+ sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages;
/* loop till all the entries in in array are not processed */
while (current_entry < sep_lli_entries) {
+
/* set the new input and output tables */
- in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
+ in_lli_table_ptr =
+ (struct sep_lli_entry_t *)lli_table_alloc_addr;
+
+ lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+
+ if (lli_table_alloc_addr >
+ ((u32)sep->shared_addr +
+ SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
+ SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) {
+
+ error = -ENOMEM;
+ goto end_function_error;
- lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+ }
+
+ /* update the number of created tables */
+ sep->num_lli_tables_created++;
/* calculate the maximum size of data for input table */
- table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry));
+ table_data_size = sep_calculate_lli_table_max_size(sep,
+ &lli_array_ptr[current_entry],
+ (sep_lli_entries - current_entry),
+ &last_table_flag);
- /* now calculate the table size so that it will be module block size */
- table_data_size = (table_data_size / block_size) * block_size;
+ /* if this is not the last table -
+ then allign it to the block size */
+ if (!last_table_flag)
+ table_data_size =
+ (table_data_size / block_size) * block_size;
- edbg("SEP Driver:output table_data_size is %lu\n", table_data_size);
+ dev_dbg(&sep->pdev->dev,
+ "output table_data_size is %x\n",
+ table_data_size);
/* construct input lli table */
- sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, &current_entry, &num_entries_in_table, table_data_size);
+ sep_build_lli_table(sep, &lli_array_ptr[current_entry],
+ in_lli_table_ptr,
+ &current_entry, &num_entries_in_table, table_data_size);
if (info_entry_ptr == 0) {
+
/* set the output parameters to physical addresses */
+ *lli_table_ptr = sep_shared_area_virt_to_bus(sep,
+ in_lli_table_ptr);
*num_entries_ptr = num_entries_in_table;
*table_data_size_ptr = table_data_size;
- edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr);
- } else {
+ dev_dbg(&sep->pdev->dev,
+ "output lli_table_in_ptr is %08x\n",
+ (u32)*lli_table_ptr);
+
+ }
+
+ else {
+
/* update the info entry of the previous in table */
- info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
+ info_entry_ptr->bus_address =
+ sep_shared_area_virt_to_bus(sep,
+ in_lli_table_ptr);
+ info_entry_ptr->block_size =
+ ((num_entries_in_table) << 24) |
+ (table_data_size);
}
/* save the pointer to the info entry of the current tables */
info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
+
}
/* print input tables */
sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *)
- sep_shared_bus_to_virt(sep, *lli_table_ptr), *num_entries_ptr, *table_data_size_ptr);
+ sep_shared_area_bus_to_virt(sep, *lli_table_ptr),
+ *num_entries_ptr,
+ *table_data_size_ptr);
/* the array of the pages */
kfree(lli_array_ptr);
+
+update_dcb_counter:
+
+ /* update dcb counter */
+ sep->nr_dcb_creat++;
+
+ goto end_function;
+
+end_function_error:
+
+ /* free all the allocated resources */
+ kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_map_array);
+ kfree(lli_array_ptr);
+ kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_page_array);
+
end_function:
- dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
- return 0;
-}
+ dev_dbg(&sep->pdev->dev,
+ "sep_prepare_input_dma_table end\n");
+
+ return error;
+}
/*
This function creates the input and output dma tables for
symmetric operations (AES/DES) according to the block size from LLI arays
+ @sep: pointer to struct_sep
+ @lli_in_array:
+ @sep_in_lli_entries:
+ @lli_out_array:
+ @sep_out_lli_entries
+ @block_size
+ @lli_table_in_ptr
+ @lli_table_out_ptr
+ @in_num_entries_ptr
+ @out_num_entries_ptr
+ @table_data_size_ptr
*/
-static int sep_construct_dma_tables_from_lli(struct sep_device *sep,
- 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)
+static int sep_construct_dma_tables_from_lli(
+ struct sep_device *sep,
+ struct sep_lli_entry_t *lli_in_array,
+ u32 sep_in_lli_entries,
+ struct sep_lli_entry_t *lli_out_array,
+ u32 sep_out_lli_entries,
+ u32 block_size,
+ dma_addr_t *lli_table_in_ptr,
+ dma_addr_t *lli_table_out_ptr,
+ u32 *in_num_entries_ptr,
+ u32 *out_num_entries_ptr,
+ u32 *table_data_size_ptr)
{
- /* points to the area where next lli table can be allocated: keep void *
- as there is pointer scaling to fix otherwise */
- void *lli_table_alloc_addr;
+ /* points to the area where next lli table can be allocated */
+ u32 lli_table_alloc_addr = 0;
+
/* input lli table */
- struct sep_lli_entry_t *in_lli_table_ptr;
+ struct sep_lli_entry_t *in_lli_table_ptr = 0;
+
/* output lli table */
- struct sep_lli_entry_t *out_lli_table_ptr;
+ struct sep_lli_entry_t *out_lli_table_ptr = 0;
+
/* pointer to the info entry of the table - the last entry */
- struct sep_lli_entry_t *info_in_entry_ptr;
+ struct sep_lli_entry_t *info_in_entry_ptr = 0;
+
/* pointer to the info entry of the table - the last entry */
- struct sep_lli_entry_t *info_out_entry_ptr;
+ struct sep_lli_entry_t *info_out_entry_ptr = 0;
+
/* points to the first entry to be processed in the lli_in_array */
- unsigned long current_in_entry;
+ u32 current_in_entry = 0;
+
/* points to the first entry to be processed in the lli_out_array */
- unsigned long current_out_entry;
+ u32 current_out_entry = 0;
+
/* max size of the input table */
- unsigned long in_table_data_size;
+ u32 in_table_data_size = 0;
+
/* max size of the output table */
- unsigned long out_table_data_size;
- /* flag te signifies if this is the first tables build from the arrays */
- unsigned long first_table_flag;
+ u32 out_table_data_size = 0;
+
+ /* flag te signifies if this is the last tables build */
+ u32 last_table_flag = 0;
+
/* the data size that should be in table */
- unsigned long table_data_size;
+ u32 table_data_size = 0;
+
/* number of etnries in the input table */
- unsigned long num_entries_in_table;
+ u32 num_entries_in_table = 0;
+
/* number of etnries in the output table */
- unsigned long num_entries_out_table;
+ u32 num_entries_out_table = 0;
- dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
+ /*---------------------
+ CODE
+ ------------------------*/
- /* initiate to pint after the message area */
- lli_table_alloc_addr = sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+ dev_dbg(&sep->pdev->dev,
+ "sep_construct_dma_tables_from_lli start\n");
- current_in_entry = 0;
- current_out_entry = 0;
- first_table_flag = 1;
- info_in_entry_ptr = 0;
- info_out_entry_ptr = 0;
+ /* initiate to point after the message area */
+ lli_table_alloc_addr = (u32)(sep->shared_addr +
+ SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
+ (sep->num_lli_tables_created *
+ (sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP)));
/* loop till all the entries in in array are not processed */
while (current_in_entry < sep_in_lli_entries) {
+
/* set the new input and output tables */
- in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
+ in_lli_table_ptr =
+ (struct sep_lli_entry_t *)lli_table_alloc_addr;
- lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+ lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
/* set the first output tables */
- out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
+ out_lli_table_ptr =
+ (struct sep_lli_entry_t *)lli_table_alloc_addr;
+
+ /* check if the DMA table area limit was overrun */
+ if ((lli_table_alloc_addr + sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP) >
+ ((u32)sep->shared_addr +
+ SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
+ SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) {
+
+ dev_warn(&sep->pdev->dev,
+ "dma table limit overrun\n");
+ return -ENOMEM;
+ }
+
+ /* update the number of the lli tables created */
+ sep->num_lli_tables_created += 2;
- lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+ lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
+ SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
/* calculate the maximum size of data for input table */
- in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry));
+ in_table_data_size =
+ sep_calculate_lli_table_max_size(sep,
+ &lli_in_array[current_in_entry],
+ (sep_in_lli_entries - current_in_entry),
+ &last_table_flag);
/* calculate the maximum size of data for output table */
- out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry));
+ out_table_data_size =
+ sep_calculate_lli_table_max_size(sep,
+ &lli_out_array[current_out_entry],
+ (sep_out_lli_entries - current_out_entry),
+ &last_table_flag);
- edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
- edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
+ dev_dbg(&sep->pdev->dev,
+ "in_table_data_size is %x\n",
+ in_table_data_size);
+
+ dev_dbg(&sep->pdev->dev,
+ "out_table_data_size is %x\n",
+ out_table_data_size);
- /* check where the data is smallest */
table_data_size = in_table_data_size;
- if (table_data_size > out_table_data_size)
- table_data_size = out_table_data_size;
- /* now calculate the table size so that it will be module block size */
- table_data_size = (table_data_size / block_size) * block_size;
+ if (!last_table_flag) {
+ /* if this is not the last table,
+ then must check where the data is smallest
+ and then align it to the block size */
+ if (table_data_size > out_table_data_size)
+ table_data_size = out_table_data_size;
+
+ /* now calculate the table size so that
+ it will be module block size */
+ table_data_size = (table_data_size / block_size) *
+ block_size;
+ }
- dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
+ dev_dbg(&sep->pdev->dev,
+ "table_data_size is %x\n", table_data_size);
/* construct input lli table */
- sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, &current_in_entry, &num_entries_in_table, table_data_size);
+ sep_build_lli_table(sep, &lli_in_array[current_in_entry],
+ in_lli_table_ptr,
+ &current_in_entry,
+ &num_entries_in_table,
+ table_data_size);
/* construct output lli table */
- sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, &current_out_entry, &num_entries_out_table, table_data_size);
+ sep_build_lli_table(sep, &lli_out_array[current_out_entry],
+ out_lli_table_ptr,
+ &current_out_entry,
+ &num_entries_out_table,
+ table_data_size);
/* if info entry is null - this is the first table built */
if (info_in_entry_ptr == 0) {
/* set the output parameters to physical addresses */
+ *lli_table_in_ptr =
+ sep_shared_area_virt_to_bus(sep, in_lli_table_ptr);
+
*in_num_entries_ptr = num_entries_in_table;
+
+ *lli_table_out_ptr =
+ sep_shared_area_virt_to_bus(sep,
+ out_lli_table_ptr);
+
*out_num_entries_ptr = num_entries_out_table;
*table_data_size_ptr = table_data_size;
- edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
- edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "output lli_table_in_ptr is %08x\n",
+ (u32)*lli_table_in_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "output lli_table_out_ptr is %08x\n",
+ (u32)*lli_table_out_ptr);
} else {
/* update the info entry of the previous in table */
- info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
+ info_in_entry_ptr->bus_address =
+ sep_shared_area_virt_to_bus(sep,
+ in_lli_table_ptr);
+
+ info_in_entry_ptr->block_size =
+ ((num_entries_in_table) << 24) |
+ (table_data_size);
/* update the info entry of the previous in table */
- info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size);
+ info_out_entry_ptr->bus_address =
+ sep_shared_area_virt_to_bus(sep,
+ out_lli_table_ptr);
+
+ info_out_entry_ptr->block_size =
+ ((num_entries_out_table) << 24) |
+ (table_data_size);
+
+ dev_dbg(&sep->pdev->dev,
+ "output lli_table_in_ptr:%08x %08x\n",
+ (u32)info_in_entry_ptr->bus_address,
+ info_in_entry_ptr->block_size);
+
+ dev_dbg(&sep->pdev->dev,
+ "output lli_table_out_ptr:%08x %08x\n",
+ (u32)info_out_entry_ptr->bus_address,
+ info_out_entry_ptr->block_size);
}
/* save the pointer to the info entry of the current tables */
- info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
- info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
+ info_in_entry_ptr = in_lli_table_ptr +
+ num_entries_in_table - 1;
+ info_out_entry_ptr = out_lli_table_ptr +
+ num_entries_out_table - 1;
- edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table);
- edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr);
- edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "output num_entries_out_table is %x\n",
+ (u32)num_entries_out_table);
+ dev_dbg(&sep->pdev->dev,
+ "output info_in_entry_ptr is %x\n",
+ (u32)info_in_entry_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "output info_out_entry_ptr is %x\n",
+ (u32)info_out_entry_ptr);
}
/* print input tables */
- sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *)
- sep_shared_bus_to_virt(sep, *lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr);
+ sep_debug_print_lli_tables(sep,
+ (struct sep_lli_entry_t *)
+ sep_shared_area_bus_to_virt(sep, *lli_table_in_ptr),
+ *in_num_entries_ptr,
+ *table_data_size_ptr);
+
/* print output tables */
- sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *)
- sep_shared_bus_to_virt(sep, *lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr);
- dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
+ sep_debug_print_lli_tables(sep,
+ (struct sep_lli_entry_t *)
+ sep_shared_area_bus_to_virt(sep, *lli_table_out_ptr),
+ *out_num_entries_ptr,
+ *table_data_size_ptr);
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_construct_dma_tables_from_lli end\n");
+
return 0;
}
-
/*
- 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
+ This function builds input and output DMA tables for synhronic
+ symmetric operations (AES, DES, HASH). It also checks that each table
+ is of the modular block size
*/
static int sep_prepare_input_output_dma_table(struct sep_device *sep,
- 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 app_virt_in_addr,
+ unsigned long app_virt_out_addr,
+ u32 data_size,
+ u32 block_size,
+ dma_addr_t *lli_table_in_ptr,
+ dma_addr_t *lli_table_out_ptr,
+ u32 *in_num_entries_ptr,
+ u32 *out_num_entries_ptr,
+ u32 *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");
+ /* error */
+ int error = 0;
+
+ /*------------------------
+ CODE
+ --------------------------*/
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_prepare_input_output_dma_table start\n");
+
+ if (data_size == 0) {
+
+ /* prepare empty table for input and output */
+ sep_prepare_empty_lli_table(sep, lli_table_in_ptr,
+ in_num_entries_ptr, table_data_size_ptr);
+
+ sep_prepare_empty_lli_table(sep, lli_table_out_ptr,
+ out_num_entries_ptr, table_data_size_ptr);
+
+ goto update_dcb_counter;
+ }
/* initialize the pages pointers */
- sep->in_page_array = 0;
- sep->out_page_array = 0;
+ sep->dma_res_arr[sep->nr_dcb_creat].in_page_array = 0;
+ sep->dma_res_arr[sep->nr_dcb_creat].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(sep, app_virt_in_addr, data_size, &sep->in_num_pages, &lli_in_array, &sep->in_page_array);
- if (result) {
- edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
+
+ /* lock the pages of the kernel buffer and
+ translate them to pages */
+ error = sep_lock_kernel_pages(sep, app_virt_in_addr,
+ data_size, &lli_in_array, SEP_DRIVER_IN_FLAG);
+
+ if (error) {
+
+ dev_warn(&sep->pdev->dev,
+ "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(sep, app_virt_in_addr, data_size, &sep->in_num_pages, &lli_in_array, &sep->in_page_array);
- if (result) {
- edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
+ }
+
+ else {
+
+ /* lock the pages of the user buffer and
+ translate them to pages */
+ error = sep_lock_user_pages(sep, app_virt_in_addr,
+ data_size, &lli_in_array, SEP_DRIVER_IN_FLAG);
+ if (error) {
+ dev_warn(&sep->pdev->dev,
+ "sep_lock_user_pages for input virtual"
+ " buffer failed\n");
goto end_function;
}
}
if (isKernelVirtualAddress == true) {
- result = sep_lock_kernel_pages(sep, app_virt_out_addr, data_size, &sep->out_num_pages, &lli_out_array, &sep->out_page_array);
- if (result) {
- edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
- goto end_function_with_error1;
+ error = sep_lock_kernel_pages(sep, app_virt_out_addr,
+ data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG);
+
+ if (error) {
+ dev_warn(&sep->pdev->dev,
+ "sep_lock_kernel_pages \
+ for output virtual buffer failed\n");
+ goto end_function_free_lli_in;
}
- } else {
- result = sep_lock_user_pages(sep, app_virt_out_addr, data_size, &sep->out_num_pages, &lli_out_array, &sep->out_page_array);
- if (result) {
- edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
- goto end_function_with_error1;
+
+ }
+
+ else {
+ error = sep_lock_user_pages(sep, app_virt_out_addr,
+ data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG);
+
+ if (error) {
+ dev_warn(&sep->pdev->dev,
+ "sep_lock_user_pages \
+ for output virtual buffer failed\n");
+ goto end_function_free_lli_in;
}
}
- edbg("sep->in_num_pages is %lu\n", sep->in_num_pages);
- edbg("sep->out_num_pages is %lu\n", sep->out_num_pages);
- edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_in_num_pages is %x\n",
+ sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages);
+ dev_dbg(&sep->pdev->dev,
+ "sep_out_num_pages is %x\n",
+ sep->dma_res_arr[sep->nr_dcb_creat].out_num_pages);
+ dev_dbg(&sep->pdev->dev,
+ "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(sep, lli_in_array, sep->in_num_pages, lli_out_array, sep->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;
+ error = sep_construct_dma_tables_from_lli(sep, lli_in_array,
+ sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages,
+ lli_out_array,
+ sep->dma_res_arr[sep->nr_dcb_creat].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 (error) {
+ dev_warn(&sep->pdev->dev,
+ "sep_construct_dma_tables_from_lli failed\n");
+ goto end_function_with_error;
}
+ kfree(lli_out_array);
+ kfree(lli_in_array);
+
+update_dcb_counter:
+
+ /* update dcb counter */
+ sep->nr_dcb_creat++;
+
/* 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:
+ dev_dbg(&sep->pdev->dev,
+ "in_num_entries_ptr is %08x\n", *in_num_entries_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "out_num_entries_ptr is %08x\n", *out_num_entries_ptr);
+ dev_dbg(&sep->pdev->dev,
+ "table_data_size_ptr is %08x\n", *table_data_size_ptr);
+
+ goto end_function;
+
+end_function_with_error:
+
+ kfree(sep->dma_res_arr[sep->nr_dcb_creat].out_map_array);
+ kfree(sep->dma_res_arr[sep->nr_dcb_creat].out_page_array);
kfree(lli_out_array);
-end_function_with_error1:
+
+
+end_function_free_lli_in:
+
+ kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_map_array);
+ kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_page_array);
kfree(lli_in_array);
+
end_function:
- dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result);
- return result;
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_prepare_input_output_dma_table"
+ " end result = %d\n", error);
+
+ return error;
}
/*
- 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(struct sep_device *sep,
- unsigned long arg)
+ This function prepares the linked dma tables and puts the
+ address for the linked list of tables inta a dcb (data control
+ block) the address of which is known by the sep hardware
+ @app_in_address: unsigned long; for data buffer in (user space)
+ @app_out_address: unsigned long; for data buffer out (user space)
+ @data_in_size: u32; for size of data
+ @block_size: u32; for block size
+ @tail_block_size: u32; for size of tail block
+ @isApplet: bool; to indicate external app
+ @isKernelVirtualAddress: bool; to indicate kernel space
+ */
+static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
+ unsigned long app_in_address,
+ unsigned long app_out_address,
+ u32 data_in_size,
+ u32 block_size,
+ u32 tail_block_size,
+ bool isApplet,
+ bool isKernelVirtualAddress)
+
{
- int error;
- /* command arguments */
- struct sep_driver_build_sync_table_t command_args;
+ /* error */
+ int error = 0;
- dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
+ /* size of tail */
+ u32 tail_size = 0;
- error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
- if (error)
+ /* address of the created dcb table */
+ struct sep_dcb_t *dcb_table_ptr = 0;
+
+ /* the physical address of the first input DMA table */
+ dma_addr_t in_first_mlli_address = 0;
+
+ /* number of entries in the first input DMA table */
+ u32 in_first_num_entries = 0;
+
+ /* the physical address of the first output DMA table */
+ dma_addr_t out_first_mlli_address = 0;
+
+ /* number of entries in the first output DMA table */
+ u32 out_first_num_entries = 0;
+
+ /* data in the first input/output table */
+ u32 first_data_size = 0;
+
+ dev_dbg(&sep->pdev->dev,
+ "prepare_input_output_dma_table_in_dcb start\n");
+
+ if (sep->nr_dcb_creat == SEP_MAX_NUM_SYNC_DMA_OPS) {
+
+ /*No more DCBS to allocate*/
+ dev_warn(&sep->pdev->dev, "no more dcb's available\n");
+ error = -EFAULT;
goto end_function;
+ }
- 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);
+ /* allocate new DCB */
+ dcb_table_ptr = (struct sep_dcb_t *)(sep->shared_addr +
+ SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES +
+ (sep->nr_dcb_creat * sizeof(struct sep_dcb_t)));
+
+ /* set the default values in the dcb */
+ dcb_table_ptr->input_mlli_address = 0;
+ dcb_table_ptr->input_mlli_num_entries = 0;
+ dcb_table_ptr->input_mlli_data_size = 0;
+ dcb_table_ptr->output_mlli_address = 0;
+ dcb_table_ptr->output_mlli_num_entries = 0;
+ dcb_table_ptr->output_mlli_data_size = 0;
+ dcb_table_ptr->tail_data_size = 0;
+ dcb_table_ptr->out_vr_tail_pt = 0;
+
+ if (isApplet == true) {
+ tail_size = data_in_size % block_size;
+
+ if (tail_size) {
+
+ if (data_in_size < tail_block_size) {
+ dev_warn(&sep->pdev->dev,
+ "data in size smaller than tail"
+ " block size\n");
+ error = -EFAULT;
+ goto end_function;
+ }
+
+ if (tail_block_size)
+ /* case the tail size should be
+ bigger than the real block size */
+ tail_size = tail_block_size +
+ ((data_in_size -
+ tail_block_size) % block_size);
+ }
+
+ /* check if there is enough data for dma operation */
+ if (data_in_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) {
+
+ if (isKernelVirtualAddress == true) {
+ memcpy(dcb_table_ptr->tail_data,
+ (void *)app_in_address, data_in_size);
+ }
+ else {
+ if (copy_from_user(dcb_table_ptr->tail_data,
+ (void *)app_in_address,
+ data_in_size)) {
+
+ dev_warn(&sep->pdev->dev,
+ "failed to copy tail\n");
+ error = -EFAULT;
+ goto end_function;
+ }
+ }
+
+ dcb_table_ptr->tail_data_size = data_in_size;
+
+ /* set the output user-space address for mem2mem op */
+ if (app_out_address)
+ dcb_table_ptr->out_vr_tail_pt =
+ (void *)app_out_address;
+
+ /*Update both data length parameters in order to avoid
+ second data copy and allow building of empty mlli
+ tables */
+ tail_size = 0x0;
+ data_in_size = 0x0;
+ }
+
+ if (tail_size) {
+
+ if (isKernelVirtualAddress == true) {
+ memcpy(dcb_table_ptr->tail_data,
+ (void *)(app_in_address + data_in_size -
+ tail_size), tail_size);
+ }
+
+ else {
+ /* we have tail data - copy it to dcb */
+ if (copy_from_user(dcb_table_ptr->tail_data,
+ (void *)(app_in_address +
+ data_in_size - tail_size),
+ tail_size)) {
+
+
+ dev_warn(&sep->pdev->dev,
+ "failed to copy tail\n");
+ error = -EFAULT;
+ goto end_function;
+ }
+ }
+
+ if (app_out_address)
+ /*Caclulate the output address
+ according to tail data size.*/
+ dcb_table_ptr->out_vr_tail_pt =
+ (void *)(app_out_address +
+ data_in_size - tail_size);
+
+ /*save the real tail data size*/
+ dcb_table_ptr->tail_data_size = tail_size;
+ /*Update the data size without the tail
+ data size AKA data for the dma*/
+ data_in_size = (data_in_size - tail_size);
+ }
+ }
+
+ /* create the MLLI tables */
/* check if we need to build only input table or input/output */
- if (command_args.app_out_address)
- /* prepare input and output tables */
+ if (app_out_address) {
+ /* prepare input/output tables */
error = sep_prepare_input_output_dma_table(sep,
- 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
+ app_in_address,
+ app_out_address,
+ data_in_size,
+ block_size,
+ &in_first_mlli_address,
+ &out_first_mlli_address,
+ &in_first_num_entries,
+ &out_first_num_entries,
+ &first_data_size,
+ isKernelVirtualAddress);
+ }
+
+ else {
/* prepare input tables */
error = sep_prepare_input_dma_table(sep,
- 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);
+ app_in_address,
+ data_in_size,
+ block_size,
+ &in_first_mlli_address,
+ &in_first_num_entries,
+ &first_data_size,
+ isKernelVirtualAddress);
+ }
- if (error)
+ if (error) {
+ dev_warn(&sep->pdev->dev, "prepare dma table call failed"
+ " from prepare dcb call\n");
goto end_function;
- /* copy to user */
- if (copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t)))
- error = -EFAULT;
+ }
+
+ /* set the dcb values */
+ dcb_table_ptr->input_mlli_address = in_first_mlli_address;
+ dcb_table_ptr->input_mlli_num_entries = in_first_num_entries;
+ dcb_table_ptr->input_mlli_data_size = first_data_size;
+ dcb_table_ptr->output_mlli_address = out_first_mlli_address;
+ dcb_table_ptr->output_mlli_num_entries = out_first_num_entries;
+ dcb_table_ptr->output_mlli_data_size = first_data_size;
+
end_function:
- dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_prepare_input_output_dma_table_in_dcb end\n");
return error;
+
}
+
/*
- this function handles the request for freeing dma table for synhronic actions
+ this function handles tha request for creation of the DMA table
+ for the synchronic symmetric operations (AES,DES)
+ @sep: pointer to struct sep_device
+ @arg: pointer to struct sep_driver_build_sync_table_t
*/
-static int sep_free_dma_table_data_handler(struct sep_device *sep)
+static int sep_create_sync_dma_tables_handler(struct sep_device *sep,
+ unsigned long arg)
{
- dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
+ int error = 0;
- /* free input pages array */
- sep_free_dma_pages(sep->in_page_array, sep->in_num_pages, 0);
+ /* command arguments */
+ struct sep_driver_build_sync_table_t command_args;
- /* free output pages array if needed */
- if (sep->out_page_array)
- sep_free_dma_pages(sep->out_page_array, sep->out_num_pages, 1);
+ dev_dbg(&sep->pdev->dev,
+ "sep_create_sync_dma_tables_handler start\n");
- /* reset all the values */
- sep->in_page_array = 0;
- sep->out_page_array = 0;
- sep->in_num_pages = 0;
- sep->out_num_pages = 0;
- dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
- return 0;
+ error = copy_from_user(&command_args, (void *)arg,
+ sizeof(struct sep_driver_build_sync_table_t));
+ if (error) {
+ dev_warn(&sep->pdev->dev, "create dma tables;"
+ " copy_from_user fails\n");
+ goto end_function;
+ }
+
+ dev_dbg(&sep->pdev->dev,
+ "app_in_address is %08lx\n", command_args.app_in_address);
+ dev_dbg(&sep->pdev->dev,
+ "app_out_address is %08lx\n", command_args.app_out_address);
+ dev_dbg(&sep->pdev->dev,
+ "data_size is %u\n", command_args.data_in_size);
+ dev_dbg(&sep->pdev->dev,
+ "block_size is %u\n", command_args.block_size);
+
+ /* validate user parameters */
+ if (!command_args.app_in_address) {
+
+ dev_warn(&sep->pdev->dev,
+ "params validation error\n");
+
+ error = -EINVAL;
+ goto end_function;
+ }
+
+ error = sep_prepare_input_output_dma_table_in_dcb(sep,
+ command_args.app_in_address,
+ command_args.app_out_address,
+ command_args.data_in_size,
+ command_args.block_size,
+ 0x0,
+ false,
+ false);
+
+end_function:
+
+ dev_dbg(&sep->pdev->dev, "sep_create_sync_dma_tables_handler end\n");
+ return error;
}
/*
- this function returns the bus and virtual addresses of the static pool
+ This function frees the dma tables and dcb block
+ @sep: pointer to struct sep_device
+ @isApplet: indicates external application
+ @isKernelVirtualAddress: indicates kernel addresses
*/
-static int sep_get_static_pool_addr_handler(struct sep_device *sep, unsigned long arg)
+static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isApplet,
+ bool isKernelVirtualAddress)
{
- int error;
- struct sep_driver_static_pool_addr_t command_args;
- dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
+ int i = 0;
+ int error = 0;
+ int error_temp = 0;
- /*prepare the output parameters in the struct */
- command_args.physical_static_address = sep->shared_bus + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
- command_args.virtual_static_address = (unsigned long)sep->shared_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
+ struct sep_dcb_t *dcb_table_ptr;
- edbg("SEP Driver:bus_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
+ /*----------------
+ CODE
+ -----------------*/
- /* send the parameters to user application */
- error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
- dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
+ dev_dbg(&sep->pdev->dev, "sep_free_dma_tables_and_dcb start\n");
+
+ if (isApplet == true) {
+
+ /* set pointer to first dcb table */
+ dcb_table_ptr = (struct sep_dcb_t *)
+ (sep->shared_addr +
+ SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES);
+
+ /* go over each dcb and see if tail pointer must be updated */
+ for (i = 0; i < sep->nr_dcb_creat; i++, dcb_table_ptr++) {
+
+ if (dcb_table_ptr->out_vr_tail_pt) {
+
+ if (isKernelVirtualAddress == true) {
+ memcpy(dcb_table_ptr->out_vr_tail_pt,
+ dcb_table_ptr->tail_data,
+ dcb_table_ptr->tail_data_size);
+ }
+
+ else {
+ error_temp = copy_to_user(
+ dcb_table_ptr->out_vr_tail_pt,
+ dcb_table_ptr->tail_data,
+ dcb_table_ptr->tail_data_size);
+ }
+
+ if (error_temp) {
+ /* we do not exist right away,
+ since we need to release
+ the dma resource */
+
+ error = error_temp;
+ }
+ }
+ }
+ }
+
+ /* free the output pages, if any */
+ sep_free_dma_table_data_handler(sep);
+
+ dev_dbg(&sep->pdev->dev, "sep_free_dma_tables_and_dcb end\n");
return error;
}
/*
- this address gets the offset of the physical address from the start
- of the mapped area
+ this function sets the bus and virtual addresses of the static pool
+ and returns the virtual address
*/
-static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsigned long arg)
+static int sep_get_static_pool_addr_handler(struct sep_device *sep,
+ unsigned long arg)
{
- int error;
- struct sep_driver_get_mapped_offset_t command_args;
+ int error = 0;
+ struct sep_driver_static_pool_addr_t command_args;
- dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
+ u32 *static_pool_addr = 0;
- error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
- if (error)
- goto end_function;
+ dev_dbg(&sep->pdev->dev, "sep_get_static_pool_addr_handler start\n");
- if (command_args.physical_address < sep->shared_bus) {
- error = -EINVAL;
- goto end_function;
- }
+ static_pool_addr = (u32 *)(sep->shared_addr +
+ SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES);
+
+ static_pool_addr[0] = SEP_STATIC_POOL_VAL_TOKEN;
+ static_pool_addr[1] = sep->shared_bus +
+ SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
- /*prepare the output parameters in the struct */
- command_args.offset = command_args.physical_address - sep->shared_bus;
+ command_args.static_virt_address = sep->shared_addr +
+ SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
- edbg("SEP Driver:bus_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
+ dev_dbg(&sep->pdev->dev, "static pool: physical %x virtual %x\n",
+ (u32)static_pool_addr[1],
+ (u32)command_args.static_virt_address);
/* send the parameters to user application */
- error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
-end_function:
- dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
+ error = copy_to_user((void *) arg, &command_args,
+ sizeof(struct sep_driver_static_pool_addr_t));
+
+ dev_dbg(&sep->pdev->dev, "sep_get_static_pool_addr_handler end\n");
+
return error;
}
-
/*
?
*/