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