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