b1a99f76694cb58c229078a2e25cc0077a0e0b28
[linux-3.10.git] / drivers / staging / tidspbridge / pmgr / dspapi.c
1 /*
2  * dspapi.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Common DSP API functions, also includes the wrapper
7  * functions called directly by the DeviceIOControl interface.
8  *
9  * Copyright (C) 2005-2006 Texas Instruments, Inc.
10  *
11  * This package is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  *
15  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19 #include <linux/types.h>
20
21 /*  ----------------------------------- Host OS */
22 #include <dspbridge/host_os.h>
23
24 /*  ----------------------------------- DSP/BIOS Bridge */
25 #include <dspbridge/dbdefs.h>
26
27 /*  ----------------------------------- OS Adaptation Layer */
28 #include <dspbridge/ntfy.h>
29
30 /*  ----------------------------------- Platform Manager */
31 #include <dspbridge/chnl.h>
32 #include <dspbridge/dev.h>
33 #include <dspbridge/drv.h>
34
35 #include <dspbridge/proc.h>
36 #include <dspbridge/strm.h>
37
38 /*  ----------------------------------- Resource Manager */
39 #include <dspbridge/disp.h>
40 #include <dspbridge/mgr.h>
41 #include <dspbridge/node.h>
42 #include <dspbridge/rmm.h>
43
44 /*  ----------------------------------- Others */
45 #include <dspbridge/msg.h>
46 #include <dspbridge/cmm.h>
47 #include <dspbridge/io.h>
48
49 /*  ----------------------------------- This */
50 #include <dspbridge/dspapi.h>
51 #include <dspbridge/dbdcd.h>
52
53 #include <dspbridge/resourcecleanup.h>
54
55 /*  ----------------------------------- Defines, Data Structures, Typedefs */
56 #define MAX_TRACEBUFLEN 255
57 #define MAX_LOADARGS    16
58 #define MAX_NODES       64
59 #define MAX_STREAMS     16
60 #define MAX_BUFS        64
61
62 /* Used to get dspbridge ioctl table */
63 #define DB_GET_IOC_TABLE(cmd)   (DB_GET_MODULE(cmd) >> DB_MODULE_SHIFT)
64
65 /* Device IOCtl function pointer */
66 struct api_cmd {
67         u32(*fxn) (union trapped_args *args, void *pr_ctxt);
68         u32 index;
69 };
70
71 /*  ----------------------------------- Globals */
72 static u32 api_c_refs;
73
74 /*
75  *  Function tables.
76  *  The order of these functions MUST be the same as the order of the command
77  *  numbers defined in dspapi-ioctl.h  This is how an IOCTL number in user mode
78  *  turns into a function call in kernel mode.
79  */
80
81 /* MGR wrapper functions */
82 static struct api_cmd mgr_cmd[] = {
83         {mgrwrap_enum_node_info},       /* MGR_ENUMNODE_INFO */
84         {mgrwrap_enum_proc_info},       /* MGR_ENUMPROC_INFO */
85         {mgrwrap_register_object},      /* MGR_REGISTEROBJECT */
86         {mgrwrap_unregister_object},    /* MGR_UNREGISTEROBJECT */
87         {mgrwrap_wait_for_bridge_events},       /* MGR_WAIT */
88         {mgrwrap_get_process_resources_info},   /* MGR_GET_PROC_RES */
89 };
90
91 /* PROC wrapper functions */
92 static struct api_cmd proc_cmd[] = {
93         {procwrap_attach},      /* PROC_ATTACH */
94         {procwrap_ctrl},        /* PROC_CTRL */
95         {procwrap_detach},      /* PROC_DETACH */
96         {procwrap_enum_node_info},      /* PROC_ENUMNODE */
97         {procwrap_enum_resources},      /* PROC_ENUMRESOURCES */
98         {procwrap_get_state},   /* PROC_GET_STATE */
99         {procwrap_get_trace},   /* PROC_GET_TRACE */
100         {procwrap_load},        /* PROC_LOAD */
101         {procwrap_register_notify},     /* PROC_REGISTERNOTIFY */
102         {procwrap_start},       /* PROC_START */
103         {procwrap_reserve_memory},      /* PROC_RSVMEM */
104         {procwrap_un_reserve_memory},   /* PROC_UNRSVMEM */
105         {procwrap_map},         /* PROC_MAPMEM */
106         {procwrap_un_map},      /* PROC_UNMAPMEM */
107         {procwrap_flush_memory},        /* PROC_FLUSHMEMORY */
108         {procwrap_stop},        /* PROC_STOP */
109         {procwrap_invalidate_memory},   /* PROC_INVALIDATEMEMORY */
110         {procwrap_begin_dma},   /* PROC_BEGINDMA */
111         {procwrap_end_dma},     /* PROC_ENDDMA */
112 };
113
114 /* NODE wrapper functions */
115 static struct api_cmd node_cmd[] = {
116         {nodewrap_allocate},    /* NODE_ALLOCATE */
117         {nodewrap_alloc_msg_buf},       /* NODE_ALLOCMSGBUF */
118         {nodewrap_change_priority},     /* NODE_CHANGEPRIORITY */
119         {nodewrap_connect},     /* NODE_CONNECT */
120         {nodewrap_create},      /* NODE_CREATE */
121         {nodewrap_delete},      /* NODE_DELETE */
122         {nodewrap_free_msg_buf},        /* NODE_FREEMSGBUF */
123         {nodewrap_get_attr},    /* NODE_GETATTR */
124         {nodewrap_get_message}, /* NODE_GETMESSAGE */
125         {nodewrap_pause},       /* NODE_PAUSE */
126         {nodewrap_put_message}, /* NODE_PUTMESSAGE */
127         {nodewrap_register_notify},     /* NODE_REGISTERNOTIFY */
128         {nodewrap_run},         /* NODE_RUN */
129         {nodewrap_terminate},   /* NODE_TERMINATE */
130         {nodewrap_get_uuid_props},      /* NODE_GETUUIDPROPS */
131 };
132
133 /* STRM wrapper functions */
134 static struct api_cmd strm_cmd[] = {
135         {strmwrap_allocate_buffer},     /* STRM_ALLOCATEBUFFER */
136         {strmwrap_close},       /* STRM_CLOSE */
137         {strmwrap_free_buffer}, /* STRM_FREEBUFFER */
138         {strmwrap_get_event_handle},    /* STRM_GETEVENTHANDLE */
139         {strmwrap_get_info},    /* STRM_GETINFO */
140         {strmwrap_idle},        /* STRM_IDLE */
141         {strmwrap_issue},       /* STRM_ISSUE */
142         {strmwrap_open},        /* STRM_OPEN */
143         {strmwrap_reclaim},     /* STRM_RECLAIM */
144         {strmwrap_register_notify},     /* STRM_REGISTERNOTIFY */
145         {strmwrap_select},      /* STRM_SELECT */
146 };
147
148 /* CMM wrapper functions */
149 static struct api_cmd cmm_cmd[] = {
150         {cmmwrap_calloc_buf},   /* CMM_ALLOCBUF */
151         {cmmwrap_free_buf},     /* CMM_FREEBUF */
152         {cmmwrap_get_handle},   /* CMM_GETHANDLE */
153         {cmmwrap_get_info},     /* CMM_GETINFO */
154 };
155
156 /* Array used to store ioctl table sizes. It can hold up to 8 entries */
157 static u8 size_cmd[] = {
158         ARRAY_SIZE(mgr_cmd),
159         ARRAY_SIZE(proc_cmd),
160         ARRAY_SIZE(node_cmd),
161         ARRAY_SIZE(strm_cmd),
162         ARRAY_SIZE(cmm_cmd),
163 };
164
165 static inline void _cp_fm_usr(void *to, const void __user * from,
166                               int *err, unsigned long bytes)
167 {
168         if (*err)
169                 return;
170
171         if (unlikely(!from)) {
172                 *err = -EFAULT;
173                 return;
174         }
175
176         if (unlikely(copy_from_user(to, from, bytes)))
177                 *err = -EFAULT;
178 }
179
180 #define CP_FM_USR(to, from, err, n)                             \
181         _cp_fm_usr(to, from, &(err), (n) * sizeof(*(to)))
182
183 static inline void _cp_to_usr(void __user *to, const void *from,
184                               int *err, unsigned long bytes)
185 {
186         if (*err)
187                 return;
188
189         if (unlikely(!to)) {
190                 *err = -EFAULT;
191                 return;
192         }
193
194         if (unlikely(copy_to_user(to, from, bytes)))
195                 *err = -EFAULT;
196 }
197
198 #define CP_TO_USR(to, from, err, n)                             \
199         _cp_to_usr(to, from, &(err), (n) * sizeof(*(from)))
200
201 /*
202  *  ======== api_call_dev_ioctl ========
203  *  Purpose:
204  *      Call the (wrapper) function for the corresponding API IOCTL.
205  */
206 inline int api_call_dev_ioctl(u32 cmd, union trapped_args *args,
207                                       u32 *result, void *pr_ctxt)
208 {
209         u32(*ioctl_cmd) (union trapped_args *args, void *pr_ctxt) = NULL;
210         int i;
211
212         if (_IOC_TYPE(cmd) != DB) {
213                 pr_err("%s: Incompatible dspbridge ioctl number\n", __func__);
214                 goto err;
215         }
216
217         if (DB_GET_IOC_TABLE(cmd) > ARRAY_SIZE(size_cmd)) {
218                 pr_err("%s: undefined ioctl module\n", __func__);
219                 goto err;
220         }
221
222         /* Check the size of the required cmd table */
223         i = DB_GET_IOC(cmd);
224         if (i > size_cmd[DB_GET_IOC_TABLE(cmd)]) {
225                 pr_err("%s: requested ioctl %d out of bounds for table %d\n",
226                        __func__, i, DB_GET_IOC_TABLE(cmd));
227                 goto err;
228         }
229
230         switch (DB_GET_MODULE(cmd)) {
231         case DB_MGR:
232                 ioctl_cmd = mgr_cmd[i].fxn;
233                 break;
234         case DB_PROC:
235                 ioctl_cmd = proc_cmd[i].fxn;
236                 break;
237         case DB_NODE:
238                 ioctl_cmd = node_cmd[i].fxn;
239                 break;
240         case DB_STRM:
241                 ioctl_cmd = strm_cmd[i].fxn;
242                 break;
243         case DB_CMM:
244                 ioctl_cmd = cmm_cmd[i].fxn;
245                 break;
246         }
247
248         if (!ioctl_cmd) {
249                 pr_err("%s: requested ioctl not defined\n", __func__);
250                 goto err;
251         } else {
252                 *result = (*ioctl_cmd) (args, pr_ctxt);
253         }
254
255         return 0;
256
257 err:
258         return -EINVAL;
259 }
260
261 /*
262  *  ======== api_exit ========
263  */
264 void api_exit(void)
265 {
266         api_c_refs--;
267
268         if (api_c_refs == 0) {
269                 /* Release all modules initialized in api_init(). */
270                 dev_exit();
271                 chnl_exit();
272                 msg_exit();
273                 io_exit();
274                 strm_exit();
275                 mgr_exit();
276                 rmm_exit();
277         }
278 }
279
280 /*
281  *  ======== api_init ========
282  *  Purpose:
283  *      Module initialization used by Bridge API.
284  */
285 bool api_init(void)
286 {
287         bool ret = true;
288         bool fdev, fchnl, fmsg, fio;
289         bool fmgr, fstrm, frmm;
290
291         if (api_c_refs == 0) {
292                 /* initialize driver and other modules */
293                 fmgr = mgr_init();
294                 fstrm = strm_init();
295                 frmm = rmm_init();
296                 fchnl = chnl_init();
297                 fmsg = msg_mod_init();
298                 fio = io_init();
299                 fdev = dev_init();
300                 ret = fdev && fchnl && fmsg && fio;
301                 ret = ret && fmgr && frmm;
302                 if (!ret) {
303
304                         if (fmgr)
305                                 mgr_exit();
306
307                         if (fstrm)
308                                 strm_exit();
309
310                         if (fchnl)
311                                 chnl_exit();
312
313                         if (fmsg)
314                                 msg_exit();
315
316                         if (fio)
317                                 io_exit();
318
319                         if (fdev)
320                                 dev_exit();
321
322                         if (frmm)
323                                 rmm_exit();
324
325                 }
326         }
327         if (ret)
328                 api_c_refs++;
329
330         return ret;
331 }
332
333 /*
334  *  ======== api_init_complete2 ========
335  *  Purpose:
336  *      Perform any required bridge initialization which cannot
337  *      be performed in api_init() or dev_start_device() due
338  *      to the fact that some services are not yet
339  *      completely initialized.
340  *  Parameters:
341  *  Returns:
342  *      0:      Allow this device to load
343  *      -EPERM:      Failure.
344  *  Requires:
345  *      Bridge API initialized.
346  *  Ensures:
347  */
348 int api_init_complete2(void)
349 {
350         int status = 0;
351         struct cfg_devnode *dev_node;
352         struct dev_object *hdev_obj;
353         struct drv_data *drv_datap;
354         u8 dev_type;
355
356         /*  Walk the list of DevObjects, get each devnode, and attempting to
357          *  autostart the board. Note that this requires COF loading, which
358          *  requires KFILE. */
359         for (hdev_obj = dev_get_first(); hdev_obj != NULL;
360              hdev_obj = dev_get_next(hdev_obj)) {
361                 if (dev_get_dev_node(hdev_obj, &dev_node))
362                         continue;
363
364                 if (dev_get_dev_type(hdev_obj, &dev_type))
365                         continue;
366
367                 if ((dev_type == DSP_UNIT) || (dev_type == IVA_UNIT)) {
368                         drv_datap = dev_get_drvdata(bridge);
369
370                         if (drv_datap && drv_datap->base_img)
371                                 proc_auto_start(dev_node, hdev_obj);
372                 }
373         }
374
375         return status;
376 }
377
378 /* TODO: Remove deprecated and not implemented ioctl wrappers */
379
380 /*
381  * ======== mgrwrap_enum_node_info ========
382  */
383 u32 mgrwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
384 {
385         u8 *pndb_props;
386         u32 num_nodes;
387         int status = 0;
388         u32 size = args->args_mgr_enumnode_info.ndb_props_size;
389
390         if (size < sizeof(struct dsp_ndbprops))
391                 return -EINVAL;
392
393         pndb_props = kmalloc(size, GFP_KERNEL);
394         if (pndb_props == NULL)
395                 status = -ENOMEM;
396
397         if (!status) {
398                 status =
399                     mgr_enum_node_info(args->args_mgr_enumnode_info.node_id,
400                                        (struct dsp_ndbprops *)pndb_props, size,
401                                        &num_nodes);
402         }
403         CP_TO_USR(args->args_mgr_enumnode_info.ndb_props, pndb_props, status,
404                   size);
405         CP_TO_USR(args->args_mgr_enumnode_info.num_nodes, &num_nodes, status,
406                   1);
407         kfree(pndb_props);
408
409         return status;
410 }
411
412 /*
413  * ======== mgrwrap_enum_proc_info ========
414  */
415 u32 mgrwrap_enum_proc_info(union trapped_args *args, void *pr_ctxt)
416 {
417         u8 *processor_info;
418         u8 num_procs;
419         int status = 0;
420         u32 size = args->args_mgr_enumproc_info.processor_info_size;
421
422         if (size < sizeof(struct dsp_processorinfo))
423                 return -EINVAL;
424
425         processor_info = kmalloc(size, GFP_KERNEL);
426         if (processor_info == NULL)
427                 status = -ENOMEM;
428
429         if (!status) {
430                 status =
431                     mgr_enum_processor_info(args->args_mgr_enumproc_info.
432                                             processor_id,
433                                             (struct dsp_processorinfo *)
434                                             processor_info, size, &num_procs);
435         }
436         CP_TO_USR(args->args_mgr_enumproc_info.processor_info, processor_info,
437                   status, size);
438         CP_TO_USR(args->args_mgr_enumproc_info.num_procs, &num_procs,
439                   status, 1);
440         kfree(processor_info);
441
442         return status;
443 }
444
445 #define WRAP_MAP2CALLER(x) x
446 /*
447  * ======== mgrwrap_register_object ========
448  */
449 u32 mgrwrap_register_object(union trapped_args *args, void *pr_ctxt)
450 {
451         u32 ret;
452         struct dsp_uuid uuid_obj;
453         u32 path_size = 0;
454         char *psz_path_name = NULL;
455         int status = 0;
456
457         CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1);
458         if (status)
459                 goto func_end;
460         /* path_size is increased by 1 to accommodate NULL */
461         path_size = strlen_user((char *)
462                                 args->args_mgr_registerobject.sz_path_name) +
463             1;
464         psz_path_name = kmalloc(path_size, GFP_KERNEL);
465         if (!psz_path_name) {
466                 status = -ENOMEM;
467                 goto func_end;
468         }
469         ret = strncpy_from_user(psz_path_name,
470                                 (char *)args->args_mgr_registerobject.
471                                 sz_path_name, path_size);
472         if (!ret) {
473                 status = -EFAULT;
474                 goto func_end;
475         }
476
477         if (args->args_mgr_registerobject.obj_type >= DSP_DCDMAXOBJTYPE) {
478                 status = -EINVAL;
479                 goto func_end;
480         }
481
482         status = dcd_register_object(&uuid_obj,
483                                      args->args_mgr_registerobject.obj_type,
484                                      (char *)psz_path_name);
485 func_end:
486         kfree(psz_path_name);
487         return status;
488 }
489
490 /*
491  * ======== mgrwrap_unregister_object ========
492  */
493 u32 mgrwrap_unregister_object(union trapped_args *args, void *pr_ctxt)
494 {
495         int status = 0;
496         struct dsp_uuid uuid_obj;
497
498         CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1);
499         if (status)
500                 goto func_end;
501
502         status = dcd_unregister_object(&uuid_obj,
503                                        args->args_mgr_unregisterobject.
504                                        obj_type);
505 func_end:
506         return status;
507
508 }
509
510 /*
511  * ======== mgrwrap_wait_for_bridge_events ========
512  */
513 u32 mgrwrap_wait_for_bridge_events(union trapped_args *args, void *pr_ctxt)
514 {
515         int status = 0;
516         struct dsp_notification *anotifications[MAX_EVENTS];
517         struct dsp_notification notifications[MAX_EVENTS];
518         u32 index, i;
519         u32 count = args->args_mgr_wait.count;
520
521         if (count > MAX_EVENTS)
522                 status = -EINVAL;
523
524         /* get the array of pointers to user structures */
525         CP_FM_USR(anotifications, args->args_mgr_wait.anotifications,
526                   status, count);
527         /* get the events */
528         for (i = 0; i < count; i++) {
529                 CP_FM_USR(&notifications[i], anotifications[i], status, 1);
530                 if (status || !notifications[i].handle) {
531                         status = -EINVAL;
532                         break;
533                 }
534                 /* set the array of pointers to kernel structures */
535                 anotifications[i] = &notifications[i];
536         }
537         if (!status) {
538                 status = mgr_wait_for_bridge_events(anotifications, count,
539                                                          &index,
540                                                          args->args_mgr_wait.
541                                                          timeout);
542         }
543         CP_TO_USR(args->args_mgr_wait.index, &index, status, 1);
544         return status;
545 }
546
547 /*
548  * ======== MGRWRAP_GetProcessResourceInfo ========
549  */
550 u32 __deprecated mgrwrap_get_process_resources_info(union trapped_args * args,
551                                                     void *pr_ctxt)
552 {
553         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
554         return 0;
555 }
556
557 /*
558  * ======== procwrap_attach ========
559  */
560 u32 procwrap_attach(union trapped_args *args, void *pr_ctxt)
561 {
562         void *processor;
563         int status = 0;
564         struct dsp_processorattrin proc_attr_in, *attr_in = NULL;
565
566         /* Optional argument */
567         if (args->args_proc_attach.attr_in) {
568                 CP_FM_USR(&proc_attr_in, args->args_proc_attach.attr_in, status,
569                           1);
570                 if (!status)
571                         attr_in = &proc_attr_in;
572                 else
573                         goto func_end;
574
575         }
576         status = proc_attach(args->args_proc_attach.processor_id, attr_in,
577                              &processor, pr_ctxt);
578         CP_TO_USR(args->args_proc_attach.ph_processor, &processor, status, 1);
579 func_end:
580         return status;
581 }
582
583 /*
584  * ======== procwrap_ctrl ========
585  */
586 u32 procwrap_ctrl(union trapped_args *args, void *pr_ctxt)
587 {
588         u32 cb_data_size, __user * psize = (u32 __user *)
589             args->args_proc_ctrl.args;
590         u8 *pargs = NULL;
591         int status = 0;
592         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
593
594         if (psize) {
595                 if (get_user(cb_data_size, psize)) {
596                         status = -EPERM;
597                         goto func_end;
598                 }
599                 cb_data_size += sizeof(u32);
600                 pargs = kmalloc(cb_data_size, GFP_KERNEL);
601                 if (pargs == NULL) {
602                         status = -ENOMEM;
603                         goto func_end;
604                 }
605
606                 CP_FM_USR(pargs, args->args_proc_ctrl.args, status,
607                           cb_data_size);
608         }
609         if (!status) {
610                 status = proc_ctrl(hprocessor,
611                                    args->args_proc_ctrl.cmd,
612                                    (struct dsp_cbdata *)pargs);
613         }
614
615         /* CP_TO_USR(args->args_proc_ctrl.args, pargs, status, 1); */
616         kfree(pargs);
617 func_end:
618         return status;
619 }
620
621 /*
622  * ======== procwrap_detach ========
623  */
624 u32 __deprecated procwrap_detach(union trapped_args * args, void *pr_ctxt)
625 {
626         /* proc_detach called at bridge_release only */
627         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
628         return 0;
629 }
630
631 /*
632  * ======== procwrap_enum_node_info ========
633  */
634 u32 procwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
635 {
636         int status;
637         void *node_tab[MAX_NODES];
638         u32 num_nodes;
639         u32 alloc_cnt;
640         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
641
642         if (!args->args_proc_enumnode_info.node_tab_size)
643                 return -EINVAL;
644
645         status = proc_enum_nodes(hprocessor,
646                                  node_tab,
647                                  args->args_proc_enumnode_info.node_tab_size,
648                                  &num_nodes, &alloc_cnt);
649         CP_TO_USR(args->args_proc_enumnode_info.node_tab, node_tab, status,
650                   num_nodes);
651         CP_TO_USR(args->args_proc_enumnode_info.num_nodes, &num_nodes,
652                   status, 1);
653         CP_TO_USR(args->args_proc_enumnode_info.allocated, &alloc_cnt,
654                   status, 1);
655         return status;
656 }
657
658 u32 procwrap_end_dma(union trapped_args *args, void *pr_ctxt)
659 {
660         int status;
661
662         if (args->args_proc_dma.dir >= DMA_NONE)
663                 return -EINVAL;
664
665         status = proc_end_dma(pr_ctxt,
666                                    args->args_proc_dma.mpu_addr,
667                                    args->args_proc_dma.size,
668                                    args->args_proc_dma.dir);
669         return status;
670 }
671
672 u32 procwrap_begin_dma(union trapped_args *args, void *pr_ctxt)
673 {
674         int status;
675
676         if (args->args_proc_dma.dir >= DMA_NONE)
677                 return -EINVAL;
678
679         status = proc_begin_dma(pr_ctxt,
680                                    args->args_proc_dma.mpu_addr,
681                                    args->args_proc_dma.size,
682                                    args->args_proc_dma.dir);
683         return status;
684 }
685
686 /*
687  * ======== procwrap_flush_memory ========
688  */
689 u32 procwrap_flush_memory(union trapped_args *args, void *pr_ctxt)
690 {
691         int status;
692
693         if (args->args_proc_flushmemory.flags >
694             PROC_WRITEBACK_INVALIDATE_MEM)
695                 return -EINVAL;
696
697         status = proc_flush_memory(pr_ctxt,
698                                    args->args_proc_flushmemory.mpu_addr,
699                                    args->args_proc_flushmemory.size,
700                                    args->args_proc_flushmemory.flags);
701         return status;
702 }
703
704 /*
705  * ======== procwrap_invalidate_memory ========
706  */
707 u32 procwrap_invalidate_memory(union trapped_args *args, void *pr_ctxt)
708 {
709         int status;
710
711         status =
712             proc_invalidate_memory(pr_ctxt,
713                                    args->args_proc_invalidatememory.mpu_addr,
714                                    args->args_proc_invalidatememory.size);
715         return status;
716 }
717
718 /*
719  * ======== procwrap_enum_resources ========
720  */
721 u32 procwrap_enum_resources(union trapped_args *args, void *pr_ctxt)
722 {
723         int status = 0;
724         struct dsp_resourceinfo resource_info;
725         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
726
727         if (args->args_proc_enumresources.resource_info_size <
728             sizeof(struct dsp_resourceinfo))
729                 return -EINVAL;
730
731         status =
732             proc_get_resource_info(hprocessor,
733                                    args->args_proc_enumresources.resource_type,
734                                    &resource_info,
735                                    args->args_proc_enumresources.
736                                    resource_info_size);
737
738         CP_TO_USR(args->args_proc_enumresources.resource_info, &resource_info,
739                   status, 1);
740
741         return status;
742
743 }
744
745 /*
746  * ======== procwrap_get_state ========
747  */
748 u32 procwrap_get_state(union trapped_args *args, void *pr_ctxt)
749 {
750         int status;
751         struct dsp_processorstate proc_state;
752         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
753
754         if (args->args_proc_getstate.state_info_size <
755             sizeof(struct dsp_processorstate))
756                 return -EINVAL;
757
758         status = proc_get_state(hprocessor, &proc_state,
759                            args->args_proc_getstate.state_info_size);
760         CP_TO_USR(args->args_proc_getstate.proc_state_obj, &proc_state, status,
761                   1);
762         return status;
763
764 }
765
766 /*
767  * ======== procwrap_get_trace ========
768  */
769 u32 procwrap_get_trace(union trapped_args *args, void *pr_ctxt)
770 {
771         int status;
772         u8 *pbuf;
773         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
774
775         if (args->args_proc_gettrace.max_size > MAX_TRACEBUFLEN)
776                 return -EINVAL;
777
778         pbuf = kzalloc(args->args_proc_gettrace.max_size, GFP_KERNEL);
779         if (pbuf != NULL) {
780                 status = proc_get_trace(hprocessor, pbuf,
781                                         args->args_proc_gettrace.max_size);
782         } else {
783                 status = -ENOMEM;
784         }
785         CP_TO_USR(args->args_proc_gettrace.buf, pbuf, status,
786                   args->args_proc_gettrace.max_size);
787         kfree(pbuf);
788
789         return status;
790 }
791
792 /*
793  * ======== procwrap_load ========
794  */
795 u32 procwrap_load(union trapped_args *args, void *pr_ctxt)
796 {
797         s32 i, len;
798         int status = 0;
799         char *temp;
800         s32 count = args->args_proc_load.argc_index;
801         u8 **argv = NULL, **envp = NULL;
802         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
803
804         if (count <= 0 || count > MAX_LOADARGS) {
805                 status = -EINVAL;
806                 goto func_cont;
807         }
808
809         argv = kmalloc(count * sizeof(u8 *), GFP_KERNEL);
810         if (!argv) {
811                 status = -ENOMEM;
812                 goto func_cont;
813         }
814
815         CP_FM_USR(argv, args->args_proc_load.user_args, status, count);
816         if (status) {
817                 kfree(argv);
818                 argv = NULL;
819                 goto func_cont;
820         }
821
822         for (i = 0; i < count; i++) {
823                 if (argv[i]) {
824                         /* User space pointer to argument */
825                         temp = (char *)argv[i];
826                         /* len is increased by 1 to accommodate NULL */
827                         len = strlen_user((char *)temp) + 1;
828                         /* Kernel space pointer to argument */
829                         argv[i] = kmalloc(len, GFP_KERNEL);
830                         if (argv[i]) {
831                                 CP_FM_USR(argv[i], temp, status, len);
832                                 if (status) {
833                                         kfree(argv[i]);
834                                         argv[i] = NULL;
835                                         goto func_cont;
836                                 }
837                         } else {
838                                 status = -ENOMEM;
839                                 goto func_cont;
840                         }
841                 }
842         }
843         /* TODO: validate this */
844         if (args->args_proc_load.user_envp) {
845                 /* number of elements in the envp array including NULL */
846                 count = 0;
847                 do {
848                         if (get_user(temp,
849                                      args->args_proc_load.user_envp + count)) {
850                                 status = -EFAULT;
851                                 goto func_cont;
852                         }
853                         count++;
854                 } while (temp);
855                 envp = kmalloc(count * sizeof(u8 *), GFP_KERNEL);
856                 if (!envp) {
857                         status = -ENOMEM;
858                         goto func_cont;
859                 }
860
861                 CP_FM_USR(envp, args->args_proc_load.user_envp, status, count);
862                 if (status) {
863                         kfree(envp);
864                         envp = NULL;
865                         goto func_cont;
866                 }
867                 for (i = 0; envp[i]; i++) {
868                         /* User space pointer to argument */
869                         temp = (char *)envp[i];
870                         /* len is increased by 1 to accommodate NULL */
871                         len = strlen_user((char *)temp) + 1;
872                         /* Kernel space pointer to argument */
873                         envp[i] = kmalloc(len, GFP_KERNEL);
874                         if (envp[i]) {
875                                 CP_FM_USR(envp[i], temp, status, len);
876                                 if (status) {
877                                         kfree(envp[i]);
878                                         envp[i] = NULL;
879                                         goto func_cont;
880                                 }
881                         } else {
882                                 status = -ENOMEM;
883                                 goto func_cont;
884                         }
885                 }
886         }
887
888         if (!status) {
889                 status = proc_load(hprocessor,
890                                    args->args_proc_load.argc_index,
891                                    (const char **)argv, (const char **)envp);
892         }
893 func_cont:
894         if (envp) {
895                 i = 0;
896                 while (envp[i])
897                         kfree(envp[i++]);
898
899                 kfree(envp);
900         }
901
902         if (argv) {
903                 count = args->args_proc_load.argc_index;
904                 for (i = 0; (i < count) && argv[i]; i++)
905                         kfree(argv[i]);
906
907                 kfree(argv);
908         }
909
910         return status;
911 }
912
913 /*
914  * ======== procwrap_map ========
915  */
916 u32 procwrap_map(union trapped_args *args, void *pr_ctxt)
917 {
918         int status;
919         void *map_addr;
920         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
921
922         if (!args->args_proc_mapmem.size)
923                 return -EINVAL;
924
925         status = proc_map(args->args_proc_mapmem.processor,
926                           args->args_proc_mapmem.mpu_addr,
927                           args->args_proc_mapmem.size,
928                           args->args_proc_mapmem.req_addr, &map_addr,
929                           args->args_proc_mapmem.map_attr, pr_ctxt);
930         if (!status) {
931                 if (put_user(map_addr, args->args_proc_mapmem.map_addr)) {
932                         status = -EINVAL;
933                         proc_un_map(hprocessor, map_addr, pr_ctxt);
934                 }
935
936         }
937         return status;
938 }
939
940 /*
941  * ======== procwrap_register_notify ========
942  */
943 u32 procwrap_register_notify(union trapped_args *args, void *pr_ctxt)
944 {
945         int status;
946         struct dsp_notification notification;
947         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
948
949         /* Initialize the notification data structure */
950         notification.name = NULL;
951         notification.handle = NULL;
952
953         status = proc_register_notify(hprocessor,
954                                  args->args_proc_register_notify.event_mask,
955                                  args->args_proc_register_notify.notify_type,
956                                  &notification);
957         CP_TO_USR(args->args_proc_register_notify.notification, &notification,
958                   status, 1);
959         return status;
960 }
961
962 /*
963  * ======== procwrap_reserve_memory ========
964  */
965 u32 procwrap_reserve_memory(union trapped_args *args, void *pr_ctxt)
966 {
967         int status;
968         void *prsv_addr;
969         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
970
971         if ((args->args_proc_rsvmem.size <= 0) ||
972             (args->args_proc_rsvmem.size & (PG_SIZE4K - 1)) != 0)
973                 return -EINVAL;
974
975         status = proc_reserve_memory(hprocessor,
976                                      args->args_proc_rsvmem.size, &prsv_addr,
977                                      pr_ctxt);
978         if (!status) {
979                 if (put_user(prsv_addr, args->args_proc_rsvmem.rsv_addr)) {
980                         status = -EINVAL;
981                         proc_un_reserve_memory(args->args_proc_rsvmem.
982                                                processor, prsv_addr, pr_ctxt);
983                 }
984         }
985         return status;
986 }
987
988 /*
989  * ======== procwrap_start ========
990  */
991 u32 procwrap_start(union trapped_args *args, void *pr_ctxt)
992 {
993         u32 ret;
994
995         ret = proc_start(((struct process_context *)pr_ctxt)->processor);
996         return ret;
997 }
998
999 /*
1000  * ======== procwrap_un_map ========
1001  */
1002 u32 procwrap_un_map(union trapped_args *args, void *pr_ctxt)
1003 {
1004         int status;
1005
1006         status = proc_un_map(((struct process_context *)pr_ctxt)->processor,
1007                              args->args_proc_unmapmem.map_addr, pr_ctxt);
1008         return status;
1009 }
1010
1011 /*
1012  * ======== procwrap_un_reserve_memory ========
1013  */
1014 u32 procwrap_un_reserve_memory(union trapped_args *args, void *pr_ctxt)
1015 {
1016         int status;
1017         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1018
1019         status = proc_un_reserve_memory(hprocessor,
1020                                         args->args_proc_unrsvmem.rsv_addr,
1021                                         pr_ctxt);
1022         return status;
1023 }
1024
1025 /*
1026  * ======== procwrap_stop ========
1027  */
1028 u32 procwrap_stop(union trapped_args *args, void *pr_ctxt)
1029 {
1030         u32 ret;
1031
1032         ret = proc_stop(((struct process_context *)pr_ctxt)->processor);
1033
1034         return ret;
1035 }
1036
1037 /*
1038  * ======== find_handle =========
1039  */
1040 inline void find_node_handle(struct node_res_object **noderes,
1041                                 void *pr_ctxt, void *hnode)
1042 {
1043         rcu_read_lock();
1044         *noderes = idr_find(((struct process_context *)pr_ctxt)->node_id,
1045                                                                 (int)hnode - 1);
1046         rcu_read_unlock();
1047         return;
1048 }
1049
1050
1051 /*
1052  * ======== nodewrap_allocate ========
1053  */
1054 u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt)
1055 {
1056         int status = 0;
1057         struct dsp_uuid node_uuid;
1058         u32 cb_data_size = 0;
1059         u32 __user *psize = (u32 __user *) args->args_node_allocate.args;
1060         u8 *pargs = NULL;
1061         struct dsp_nodeattrin proc_attr_in, *attr_in = NULL;
1062         struct node_res_object *node_res;
1063         int nodeid;
1064         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1065
1066         /* Optional argument */
1067         if (psize) {
1068                 if (get_user(cb_data_size, psize))
1069                         status = -EPERM;
1070
1071                 cb_data_size += sizeof(u32);
1072                 if (!status) {
1073                         pargs = kmalloc(cb_data_size, GFP_KERNEL);
1074                         if (pargs == NULL)
1075                                 status = -ENOMEM;
1076
1077                 }
1078                 CP_FM_USR(pargs, args->args_node_allocate.args, status,
1079                           cb_data_size);
1080         }
1081         CP_FM_USR(&node_uuid, args->args_node_allocate.node_id_ptr, status, 1);
1082         if (status)
1083                 goto func_cont;
1084         /* Optional argument */
1085         if (args->args_node_allocate.attr_in) {
1086                 CP_FM_USR(&proc_attr_in, args->args_node_allocate.attr_in,
1087                           status, 1);
1088                 if (!status)
1089                         attr_in = &proc_attr_in;
1090                 else
1091                         status = -ENOMEM;
1092
1093         }
1094         if (!status) {
1095                 status = node_allocate(hprocessor,
1096                                        &node_uuid, (struct dsp_cbdata *)pargs,
1097                                        attr_in, &node_res, pr_ctxt);
1098         }
1099         if (!status) {
1100                 nodeid = node_res->id + 1;
1101                 CP_TO_USR(args->args_node_allocate.node, &nodeid,
1102                         status, 1);
1103                 if (status) {
1104                         status = -EFAULT;
1105                         node_delete(node_res, pr_ctxt);
1106                 }
1107         }
1108 func_cont:
1109         kfree(pargs);
1110
1111         return status;
1112 }
1113
1114 /*
1115  *  ======== nodewrap_alloc_msg_buf ========
1116  */
1117 u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt)
1118 {
1119         int status = 0;
1120         struct dsp_bufferattr *pattr = NULL;
1121         struct dsp_bufferattr attr;
1122         u8 *pbuffer = NULL;
1123         struct node_res_object *node_res;
1124
1125         find_node_handle(&node_res,  pr_ctxt,
1126                                 args->args_node_allocmsgbuf.node);
1127
1128         if (!node_res)
1129                 return -EFAULT;
1130
1131         if (!args->args_node_allocmsgbuf.size)
1132                 return -EINVAL;
1133
1134         if (args->args_node_allocmsgbuf.attr) { /* Optional argument */
1135                 CP_FM_USR(&attr, args->args_node_allocmsgbuf.attr, status, 1);
1136                 if (!status)
1137                         pattr = &attr;
1138
1139         }
1140         /* argument */
1141         CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.buffer, status, 1);
1142         if (!status) {
1143                 status = node_alloc_msg_buf(node_res->node,
1144                                             args->args_node_allocmsgbuf.size,
1145                                             pattr, &pbuffer);
1146         }
1147         CP_TO_USR(args->args_node_allocmsgbuf.buffer, &pbuffer, status, 1);
1148         return status;
1149 }
1150
1151 /*
1152  * ======== nodewrap_change_priority ========
1153  */
1154 u32 nodewrap_change_priority(union trapped_args *args, void *pr_ctxt)
1155 {
1156         u32 ret;
1157         struct node_res_object *node_res;
1158
1159         find_node_handle(&node_res, pr_ctxt,
1160                                 args->args_node_changepriority.node);
1161
1162         if (!node_res)
1163                 return -EFAULT;
1164
1165         ret = node_change_priority(node_res->node,
1166                                    args->args_node_changepriority.prio);
1167
1168         return ret;
1169 }
1170
1171 /*
1172  * ======== nodewrap_connect ========
1173  */
1174 u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt)
1175 {
1176         int status = 0;
1177         struct dsp_strmattr attrs;
1178         struct dsp_strmattr *pattrs = NULL;
1179         u32 cb_data_size;
1180         u32 __user *psize = (u32 __user *) args->args_node_connect.conn_param;
1181         u8 *pargs = NULL;
1182         struct node_res_object *node_res1, *node_res2;
1183         struct node_object *node1 = NULL, *node2 = NULL;
1184
1185         if ((int)args->args_node_connect.node != DSP_HGPPNODE) {
1186                 find_node_handle(&node_res1, pr_ctxt,
1187                                 args->args_node_connect.node);
1188                 if (node_res1)
1189                         node1 = node_res1->node;
1190         } else {
1191                 node1 = args->args_node_connect.node;
1192         }
1193
1194         if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) {
1195                 find_node_handle(&node_res2, pr_ctxt,
1196                                 args->args_node_connect.other_node);
1197                 if (node_res2)
1198                         node2 = node_res2->node;
1199         } else {
1200                 node2 = args->args_node_connect.other_node;
1201         }
1202
1203         if (!node1 || !node2)
1204                 return -EFAULT;
1205
1206         /* Optional argument */
1207         if (psize) {
1208                 if (get_user(cb_data_size, psize))
1209                         status = -EPERM;
1210
1211                 cb_data_size += sizeof(u32);
1212                 if (!status) {
1213                         pargs = kmalloc(cb_data_size, GFP_KERNEL);
1214                         if (pargs == NULL) {
1215                                 status = -ENOMEM;
1216                                 goto func_cont;
1217                         }
1218
1219                 }
1220                 CP_FM_USR(pargs, args->args_node_connect.conn_param, status,
1221                           cb_data_size);
1222                 if (status)
1223                         goto func_cont;
1224         }
1225         if (args->args_node_connect.attrs) {    /* Optional argument */
1226                 CP_FM_USR(&attrs, args->args_node_connect.attrs, status, 1);
1227                 if (!status)
1228                         pattrs = &attrs;
1229
1230         }
1231         if (!status) {
1232                 status = node_connect(node1,
1233                                       args->args_node_connect.stream_id,
1234                                       node2,
1235                                       args->args_node_connect.other_stream,
1236                                       pattrs, (struct dsp_cbdata *)pargs);
1237         }
1238 func_cont:
1239         kfree(pargs);
1240
1241         return status;
1242 }
1243
1244 /*
1245  * ======== nodewrap_create ========
1246  */
1247 u32 nodewrap_create(union trapped_args *args, void *pr_ctxt)
1248 {
1249         u32 ret;
1250         struct node_res_object *node_res;
1251
1252         find_node_handle(&node_res, pr_ctxt, args->args_node_create.node);
1253
1254         if (!node_res)
1255                 return -EFAULT;
1256
1257         ret = node_create(node_res->node);
1258
1259         return ret;
1260 }
1261
1262 /*
1263  * ======== nodewrap_delete ========
1264  */
1265 u32 nodewrap_delete(union trapped_args *args, void *pr_ctxt)
1266 {
1267         u32 ret;
1268         struct node_res_object *node_res;
1269
1270         find_node_handle(&node_res, pr_ctxt, args->args_node_delete.node);
1271
1272         if (!node_res)
1273                 return -EFAULT;
1274
1275         ret = node_delete(node_res, pr_ctxt);
1276
1277         return ret;
1278 }
1279
1280 /*
1281  *  ======== nodewrap_free_msg_buf ========
1282  */
1283 u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt)
1284 {
1285         int status = 0;
1286         struct dsp_bufferattr *pattr = NULL;
1287         struct dsp_bufferattr attr;
1288         struct node_res_object *node_res;
1289
1290         find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.node);
1291
1292         if (!node_res)
1293                 return -EFAULT;
1294
1295         if (args->args_node_freemsgbuf.attr) {  /* Optional argument */
1296                 CP_FM_USR(&attr, args->args_node_freemsgbuf.attr, status, 1);
1297                 if (!status)
1298                         pattr = &attr;
1299
1300         }
1301
1302         if (!args->args_node_freemsgbuf.buffer)
1303                 return -EFAULT;
1304
1305         if (!status) {
1306                 status = node_free_msg_buf(node_res->node,
1307                                            args->args_node_freemsgbuf.buffer,
1308                                            pattr);
1309         }
1310
1311         return status;
1312 }
1313
1314 /*
1315  * ======== nodewrap_get_attr ========
1316  */
1317 u32 nodewrap_get_attr(union trapped_args *args, void *pr_ctxt)
1318 {
1319         int status = 0;
1320         struct dsp_nodeattr attr;
1321         struct node_res_object *node_res;
1322
1323         find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.node);
1324
1325         if (!node_res)
1326                 return -EFAULT;
1327
1328         status = node_get_attr(node_res->node, &attr,
1329                                args->args_node_getattr.attr_size);
1330         CP_TO_USR(args->args_node_getattr.attr, &attr, status, 1);
1331
1332         return status;
1333 }
1334
1335 /*
1336  * ======== nodewrap_get_message ========
1337  */
1338 u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt)
1339 {
1340         int status;
1341         struct dsp_msg msg;
1342         struct node_res_object *node_res;
1343
1344         find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.node);
1345
1346         if (!node_res)
1347                 return -EFAULT;
1348
1349         status = node_get_message(node_res->node, &msg,
1350                                   args->args_node_getmessage.timeout);
1351
1352         CP_TO_USR(args->args_node_getmessage.message, &msg, status, 1);
1353
1354         return status;
1355 }
1356
1357 /*
1358  * ======== nodewrap_pause ========
1359  */
1360 u32 nodewrap_pause(union trapped_args *args, void *pr_ctxt)
1361 {
1362         u32 ret;
1363         struct node_res_object *node_res;
1364
1365         find_node_handle(&node_res, pr_ctxt, args->args_node_pause.node);
1366
1367         if (!node_res)
1368                 return -EFAULT;
1369
1370         ret = node_pause(node_res->node);
1371
1372         return ret;
1373 }
1374
1375 /*
1376  * ======== nodewrap_put_message ========
1377  */
1378 u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt)
1379 {
1380         int status = 0;
1381         struct dsp_msg msg;
1382         struct node_res_object *node_res;
1383
1384         find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.node);
1385
1386         if (!node_res)
1387                 return -EFAULT;
1388
1389         CP_FM_USR(&msg, args->args_node_putmessage.message, status, 1);
1390
1391         if (!status) {
1392                 status =
1393                     node_put_message(node_res->node, &msg,
1394                                      args->args_node_putmessage.timeout);
1395         }
1396
1397         return status;
1398 }
1399
1400 /*
1401  * ======== nodewrap_register_notify ========
1402  */
1403 u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt)
1404 {
1405         int status = 0;
1406         struct dsp_notification notification;
1407         struct node_res_object *node_res;
1408
1409         find_node_handle(&node_res, pr_ctxt,
1410                         args->args_node_registernotify.node);
1411
1412         if (!node_res)
1413                 return -EFAULT;
1414
1415         /* Initialize the notification data structure */
1416         notification.name = NULL;
1417         notification.handle = NULL;
1418
1419         if (!args->args_proc_register_notify.event_mask)
1420                 CP_FM_USR(&notification,
1421                           args->args_proc_register_notify.notification,
1422                           status, 1);
1423
1424         status = node_register_notify(node_res->node,
1425                                       args->args_node_registernotify.event_mask,
1426                                       args->args_node_registernotify.
1427                                       notify_type, &notification);
1428         CP_TO_USR(args->args_node_registernotify.notification, &notification,
1429                   status, 1);
1430         return status;
1431 }
1432
1433 /*
1434  * ======== nodewrap_run ========
1435  */
1436 u32 nodewrap_run(union trapped_args *args, void *pr_ctxt)
1437 {
1438         u32 ret;
1439         struct node_res_object *node_res;
1440
1441         find_node_handle(&node_res, pr_ctxt, args->args_node_run.node);
1442
1443         if (!node_res)
1444                 return -EFAULT;
1445
1446         ret = node_run(node_res->node);
1447
1448         return ret;
1449 }
1450
1451 /*
1452  * ======== nodewrap_terminate ========
1453  */
1454 u32 nodewrap_terminate(union trapped_args *args, void *pr_ctxt)
1455 {
1456         int status;
1457         int tempstatus;
1458         struct node_res_object *node_res;
1459
1460         find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.node);
1461
1462         if (!node_res)
1463                 return -EFAULT;
1464
1465         status = node_terminate(node_res->node, &tempstatus);
1466
1467         CP_TO_USR(args->args_node_terminate.status, &tempstatus, status, 1);
1468
1469         return status;
1470 }
1471
1472 /*
1473  * ======== nodewrap_get_uuid_props ========
1474  */
1475 u32 nodewrap_get_uuid_props(union trapped_args *args, void *pr_ctxt)
1476 {
1477         int status = 0;
1478         struct dsp_uuid node_uuid;
1479         struct dsp_ndbprops *pnode_props = NULL;
1480         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1481
1482         CP_FM_USR(&node_uuid, args->args_node_getuuidprops.node_id_ptr, status,
1483                   1);
1484         if (status)
1485                 goto func_cont;
1486         pnode_props = kmalloc(sizeof(struct dsp_ndbprops), GFP_KERNEL);
1487         if (pnode_props != NULL) {
1488                 status =
1489                     node_get_uuid_props(hprocessor, &node_uuid, pnode_props);
1490                 CP_TO_USR(args->args_node_getuuidprops.node_props, pnode_props,
1491                           status, 1);
1492         } else
1493                 status = -ENOMEM;
1494 func_cont:
1495         kfree(pnode_props);
1496         return status;
1497 }
1498
1499 /*
1500  * ======== find_strm_handle =========
1501  */
1502 inline void find_strm_handle(struct strm_res_object **strmres,
1503                                 void *pr_ctxt, void *hstream)
1504 {
1505         rcu_read_lock();
1506         *strmres = idr_find(((struct process_context *)pr_ctxt)->stream_id,
1507                                                         (int)hstream - 1);
1508         rcu_read_unlock();
1509         return;
1510 }
1511
1512 /*
1513  * ======== strmwrap_allocate_buffer ========
1514  */
1515 u32 strmwrap_allocate_buffer(union trapped_args *args, void *pr_ctxt)
1516 {
1517         int status;
1518         u8 **ap_buffer = NULL;
1519         u32 num_bufs = args->args_strm_allocatebuffer.num_bufs;
1520         struct strm_res_object *strm_res;
1521
1522         find_strm_handle(&strm_res, pr_ctxt,
1523                 args->args_strm_allocatebuffer.stream);
1524
1525         if (!strm_res)
1526                 return -EFAULT;
1527
1528         if (num_bufs > MAX_BUFS)
1529                 return -EINVAL;
1530
1531         ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL);
1532         if (ap_buffer == NULL)
1533                 return -ENOMEM;
1534
1535         status = strm_allocate_buffer(strm_res,
1536                                       args->args_strm_allocatebuffer.size,
1537                                       ap_buffer, num_bufs, pr_ctxt);
1538         if (!status) {
1539                 CP_TO_USR(args->args_strm_allocatebuffer.ap_buffer, ap_buffer,
1540                           status, num_bufs);
1541                 if (status) {
1542                         status = -EFAULT;
1543                         strm_free_buffer(strm_res,
1544                                          ap_buffer, num_bufs, pr_ctxt);
1545                 }
1546         }
1547         kfree(ap_buffer);
1548
1549         return status;
1550 }
1551
1552 /*
1553  * ======== strmwrap_close ========
1554  */
1555 u32 strmwrap_close(union trapped_args *args, void *pr_ctxt)
1556 {
1557         struct strm_res_object *strm_res;
1558
1559         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_close.stream);
1560
1561         if (!strm_res)
1562                 return -EFAULT;
1563
1564         return strm_close(strm_res, pr_ctxt);
1565 }
1566
1567 /*
1568  * ======== strmwrap_free_buffer ========
1569  */
1570 u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt)
1571 {
1572         int status = 0;
1573         u8 **ap_buffer = NULL;
1574         u32 num_bufs = args->args_strm_freebuffer.num_bufs;
1575         struct strm_res_object *strm_res;
1576
1577         find_strm_handle(&strm_res, pr_ctxt,
1578                         args->args_strm_freebuffer.stream);
1579
1580         if (!strm_res)
1581                 return -EFAULT;
1582
1583         if (num_bufs > MAX_BUFS)
1584                 return -EINVAL;
1585
1586         ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL);
1587         if (ap_buffer == NULL)
1588                 return -ENOMEM;
1589
1590         CP_FM_USR(ap_buffer, args->args_strm_freebuffer.ap_buffer, status,
1591                   num_bufs);
1592
1593         if (!status)
1594                 status = strm_free_buffer(strm_res,
1595                                           ap_buffer, num_bufs, pr_ctxt);
1596
1597         CP_TO_USR(args->args_strm_freebuffer.ap_buffer, ap_buffer, status,
1598                   num_bufs);
1599         kfree(ap_buffer);
1600
1601         return status;
1602 }
1603
1604 /*
1605  * ======== strmwrap_get_event_handle ========
1606  */
1607 u32 __deprecated strmwrap_get_event_handle(union trapped_args * args,
1608                                            void *pr_ctxt)
1609 {
1610         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1611         return -ENOSYS;
1612 }
1613
1614 /*
1615  * ======== strmwrap_get_info ========
1616  */
1617 u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt)
1618 {
1619         int status = 0;
1620         struct stream_info strm_info;
1621         struct dsp_streaminfo user;
1622         struct dsp_streaminfo *temp;
1623         struct strm_res_object *strm_res;
1624
1625         find_strm_handle(&strm_res, pr_ctxt,
1626                         args->args_strm_getinfo.stream);
1627
1628         if (!strm_res)
1629                 return -EFAULT;
1630
1631         CP_FM_USR(&strm_info, args->args_strm_getinfo.stream_info, status, 1);
1632         temp = strm_info.user_strm;
1633
1634         strm_info.user_strm = &user;
1635
1636         if (!status) {
1637                 status = strm_get_info(strm_res->stream,
1638                                        &strm_info,
1639                                        args->args_strm_getinfo.
1640                                        stream_info_size);
1641         }
1642         CP_TO_USR(temp, strm_info.user_strm, status, 1);
1643         strm_info.user_strm = temp;
1644         CP_TO_USR(args->args_strm_getinfo.stream_info, &strm_info, status, 1);
1645         return status;
1646 }
1647
1648 /*
1649  * ======== strmwrap_idle ========
1650  */
1651 u32 strmwrap_idle(union trapped_args *args, void *pr_ctxt)
1652 {
1653         u32 ret;
1654         struct strm_res_object *strm_res;
1655
1656         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_idle.stream);
1657
1658         if (!strm_res)
1659                 return -EFAULT;
1660
1661         ret = strm_idle(strm_res->stream, args->args_strm_idle.flush_flag);
1662
1663         return ret;
1664 }
1665
1666 /*
1667  * ======== strmwrap_issue ========
1668  */
1669 u32 strmwrap_issue(union trapped_args *args, void *pr_ctxt)
1670 {
1671         int status = 0;
1672         struct strm_res_object *strm_res;
1673
1674         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_issue.stream);
1675
1676         if (!strm_res)
1677                 return -EFAULT;
1678
1679         if (!args->args_strm_issue.buffer)
1680                 return -EFAULT;
1681
1682         /* No need of doing CP_FM_USR for the user buffer (pbuffer)
1683            as this is done in Bridge internal function bridge_chnl_add_io_req
1684            in chnl_sm.c */
1685         status = strm_issue(strm_res->stream,
1686                             args->args_strm_issue.buffer,
1687                             args->args_strm_issue.bytes,
1688                             args->args_strm_issue.buf_size,
1689                             args->args_strm_issue.arg);
1690
1691         return status;
1692 }
1693
1694 /*
1695  * ======== strmwrap_open ========
1696  */
1697 u32 strmwrap_open(union trapped_args *args, void *pr_ctxt)
1698 {
1699         int status = 0;
1700         struct strm_attr attr;
1701         struct strm_res_object *strm_res_obj;
1702         struct dsp_streamattrin strm_attr_in;
1703         struct node_res_object *node_res;
1704         int strmid;
1705
1706         find_node_handle(&node_res, pr_ctxt, args->args_strm_open.node);
1707
1708         if (!node_res)
1709                 return -EFAULT;
1710
1711         CP_FM_USR(&attr, args->args_strm_open.attr_in, status, 1);
1712
1713         if (attr.stream_attr_in != NULL) {      /* Optional argument */
1714                 CP_FM_USR(&strm_attr_in, attr.stream_attr_in, status, 1);
1715                 if (!status) {
1716                         attr.stream_attr_in = &strm_attr_in;
1717                         if (attr.stream_attr_in->strm_mode == STRMMODE_LDMA)
1718                                 return -ENOSYS;
1719                 }
1720
1721         }
1722         status = strm_open(node_res->node,
1723                            args->args_strm_open.direction,
1724                            args->args_strm_open.index, &attr, &strm_res_obj,
1725                            pr_ctxt);
1726         if (!status) {
1727                 strmid = strm_res_obj->id + 1;
1728                 CP_TO_USR(args->args_strm_open.stream, &strmid, status, 1);
1729         }
1730         return status;
1731 }
1732
1733 /*
1734  * ======== strmwrap_reclaim ========
1735  */
1736 u32 strmwrap_reclaim(union trapped_args *args, void *pr_ctxt)
1737 {
1738         int status = 0;
1739         u8 *buf_ptr;
1740         u32 ul_bytes;
1741         u32 dw_arg;
1742         u32 ul_buf_size;
1743         struct strm_res_object *strm_res;
1744
1745         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_reclaim.stream);
1746
1747         if (!strm_res)
1748                 return -EFAULT;
1749
1750         status = strm_reclaim(strm_res->stream, &buf_ptr,
1751                               &ul_bytes, &ul_buf_size, &dw_arg);
1752         CP_TO_USR(args->args_strm_reclaim.buf_ptr, &buf_ptr, status, 1);
1753         CP_TO_USR(args->args_strm_reclaim.bytes, &ul_bytes, status, 1);
1754         CP_TO_USR(args->args_strm_reclaim.arg, &dw_arg, status, 1);
1755
1756         if (args->args_strm_reclaim.buf_size_ptr != NULL) {
1757                 CP_TO_USR(args->args_strm_reclaim.buf_size_ptr, &ul_buf_size,
1758                           status, 1);
1759         }
1760
1761         return status;
1762 }
1763
1764 /*
1765  * ======== strmwrap_register_notify ========
1766  */
1767 u32 strmwrap_register_notify(union trapped_args *args, void *pr_ctxt)
1768 {
1769         int status = 0;
1770         struct dsp_notification notification;
1771         struct strm_res_object *strm_res;
1772
1773         find_strm_handle(&strm_res, pr_ctxt,
1774                         args->args_strm_registernotify.stream);
1775
1776         if (!strm_res)
1777                 return -EFAULT;
1778
1779         /* Initialize the notification data structure */
1780         notification.name = NULL;
1781         notification.handle = NULL;
1782
1783         status = strm_register_notify(strm_res->stream,
1784                                       args->args_strm_registernotify.event_mask,
1785                                       args->args_strm_registernotify.
1786                                       notify_type, &notification);
1787         CP_TO_USR(args->args_strm_registernotify.notification, &notification,
1788                   status, 1);
1789
1790         return status;
1791 }
1792
1793 /*
1794  * ======== strmwrap_select ========
1795  */
1796 u32 strmwrap_select(union trapped_args *args, void *pr_ctxt)
1797 {
1798         u32 mask;
1799         struct strm_object *strm_tab[MAX_STREAMS];
1800         int status = 0;
1801         struct strm_res_object *strm_res;
1802         int *ids[MAX_STREAMS];
1803         int i;
1804
1805         if (args->args_strm_select.strm_num > MAX_STREAMS)
1806                 return -EINVAL;
1807
1808         CP_FM_USR(ids, args->args_strm_select.stream_tab, status,
1809                 args->args_strm_select.strm_num);
1810
1811         if (status)
1812                 return status;
1813
1814         for (i = 0; i < args->args_strm_select.strm_num; i++) {
1815                 find_strm_handle(&strm_res, pr_ctxt, ids[i]);
1816
1817                 if (!strm_res)
1818                         return -EFAULT;
1819
1820                 strm_tab[i] = strm_res->stream;
1821         }
1822
1823         if (!status) {
1824                 status = strm_select(strm_tab, args->args_strm_select.strm_num,
1825                                      &mask, args->args_strm_select.timeout);
1826         }
1827         CP_TO_USR(args->args_strm_select.mask, &mask, status, 1);
1828         return status;
1829 }
1830
1831 /* CMM */
1832
1833 /*
1834  * ======== cmmwrap_calloc_buf ========
1835  */
1836 u32 __deprecated cmmwrap_calloc_buf(union trapped_args * args, void *pr_ctxt)
1837 {
1838         /* This operation is done in kernel */
1839         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1840         return -ENOSYS;
1841 }
1842
1843 /*
1844  * ======== cmmwrap_free_buf ========
1845  */
1846 u32 __deprecated cmmwrap_free_buf(union trapped_args * args, void *pr_ctxt)
1847 {
1848         /* This operation is done in kernel */
1849         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1850         return -ENOSYS;
1851 }
1852
1853 /*
1854  * ======== cmmwrap_get_handle ========
1855  */
1856 u32 cmmwrap_get_handle(union trapped_args *args, void *pr_ctxt)
1857 {
1858         int status = 0;
1859         struct cmm_object *hcmm_mgr;
1860         void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1861
1862         status = cmm_get_handle(hprocessor, &hcmm_mgr);
1863
1864         CP_TO_USR(args->args_cmm_gethandle.cmm_mgr, &hcmm_mgr, status, 1);
1865
1866         return status;
1867 }
1868
1869 /*
1870  * ======== cmmwrap_get_info ========
1871  */
1872 u32 cmmwrap_get_info(union trapped_args *args, void *pr_ctxt)
1873 {
1874         int status = 0;
1875         struct cmm_info cmm_info_obj;
1876
1877         status = cmm_get_info(args->args_cmm_getinfo.cmm_mgr, &cmm_info_obj);
1878
1879         CP_TO_USR(args->args_cmm_getinfo.cmm_info_obj, &cmm_info_obj, status,
1880                   1);
1881
1882         return status;
1883 }