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