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