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