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