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