]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/tidspbridge/pmgr/dspapi.c
Merge branch 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[karo-tx-linux.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 __deprecated procwrap_reserve_memory(union trapped_args *args,
997                                                         void *pr_ctxt)
998 {
999         return 0;
1000 }
1001
1002 /*
1003  * ======== procwrap_start ========
1004  */
1005 u32 procwrap_start(union trapped_args *args, void *pr_ctxt)
1006 {
1007         u32 ret;
1008
1009         ret = proc_start(((struct process_context *)pr_ctxt)->hprocessor);
1010         return ret;
1011 }
1012
1013 /*
1014  * ======== procwrap_un_map ========
1015  */
1016 u32 procwrap_un_map(union trapped_args *args, void *pr_ctxt)
1017 {
1018         int status;
1019
1020         status = proc_un_map(((struct process_context *)pr_ctxt)->hprocessor,
1021                              args->args_proc_unmapmem.map_addr, pr_ctxt);
1022         return status;
1023 }
1024
1025 /*
1026  * ======== procwrap_un_reserve_memory ========
1027  */
1028 u32 __deprecated procwrap_un_reserve_memory(union trapped_args *args,
1029                                                         void *pr_ctxt)
1030 {
1031         return 0;
1032 }
1033
1034 /*
1035  * ======== procwrap_stop ========
1036  */
1037 u32 procwrap_stop(union trapped_args *args, void *pr_ctxt)
1038 {
1039         u32 ret;
1040
1041         ret = proc_stop(((struct process_context *)pr_ctxt)->hprocessor);
1042
1043         return ret;
1044 }
1045
1046 /*
1047  * ======== find_handle =========
1048  */
1049 inline void find_node_handle(struct node_res_object **noderes,
1050                                 void *pr_ctxt, void *hnode)
1051 {
1052         rcu_read_lock();
1053         *noderes = idr_find(((struct process_context *)pr_ctxt)->node_id,
1054                                                                 (int)hnode - 1);
1055         rcu_read_unlock();
1056         return;
1057 }
1058
1059
1060 /*
1061  * ======== nodewrap_allocate ========
1062  */
1063 u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt)
1064 {
1065         int status = 0;
1066         struct dsp_uuid node_uuid;
1067         u32 cb_data_size = 0;
1068         u32 __user *psize = (u32 __user *) args->args_node_allocate.pargs;
1069         u8 *pargs = NULL;
1070         struct dsp_nodeattrin proc_attr_in, *attr_in = NULL;
1071         struct node_res_object *node_res;
1072         int nodeid;
1073         void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
1074
1075         /* Optional argument */
1076         if (psize) {
1077                 if (get_user(cb_data_size, psize))
1078                         status = -EPERM;
1079
1080                 cb_data_size += sizeof(u32);
1081                 if (!status) {
1082                         pargs = kmalloc(cb_data_size, GFP_KERNEL);
1083                         if (pargs == NULL)
1084                                 status = -ENOMEM;
1085
1086                 }
1087                 CP_FM_USR(pargs, args->args_node_allocate.pargs, status,
1088                           cb_data_size);
1089         }
1090         CP_FM_USR(&node_uuid, args->args_node_allocate.node_id_ptr, status, 1);
1091         if (status)
1092                 goto func_cont;
1093         /* Optional argument */
1094         if (args->args_node_allocate.attr_in) {
1095                 CP_FM_USR(&proc_attr_in, args->args_node_allocate.attr_in,
1096                           status, 1);
1097                 if (!status)
1098                         attr_in = &proc_attr_in;
1099                 else
1100                         status = -ENOMEM;
1101
1102         }
1103         if (!status) {
1104                 status = node_allocate(hprocessor,
1105                                        &node_uuid, (struct dsp_cbdata *)pargs,
1106                                        attr_in, &node_res, pr_ctxt);
1107         }
1108         if (!status) {
1109                 nodeid = node_res->id + 1;
1110                 CP_TO_USR(args->args_node_allocate.ph_node, &nodeid,
1111                         status, 1);
1112                 if (status) {
1113                         status = -EFAULT;
1114                         node_delete(node_res, pr_ctxt);
1115                 }
1116         }
1117 func_cont:
1118         kfree(pargs);
1119
1120         return status;
1121 }
1122
1123 /*
1124  *  ======== nodewrap_alloc_msg_buf ========
1125  */
1126 u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt)
1127 {
1128         int status = 0;
1129         struct dsp_bufferattr *pattr = NULL;
1130         struct dsp_bufferattr attr;
1131         u8 *pbuffer = NULL;
1132         struct node_res_object *node_res;
1133
1134         find_node_handle(&node_res,  pr_ctxt,
1135                                 args->args_node_allocmsgbuf.hnode);
1136
1137         if (!node_res)
1138                 return -EFAULT;
1139
1140         if (!args->args_node_allocmsgbuf.usize)
1141                 return -EINVAL;
1142
1143         if (args->args_node_allocmsgbuf.pattr) {        /* Optional argument */
1144                 CP_FM_USR(&attr, args->args_node_allocmsgbuf.pattr, status, 1);
1145                 if (!status)
1146                         pattr = &attr;
1147
1148         }
1149         /* argument */
1150         CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.pbuffer, status, 1);
1151         if (!status) {
1152                 status = node_alloc_msg_buf(node_res->hnode,
1153                                             args->args_node_allocmsgbuf.usize,
1154                                             pattr, &pbuffer);
1155         }
1156         CP_TO_USR(args->args_node_allocmsgbuf.pbuffer, &pbuffer, status, 1);
1157         return status;
1158 }
1159
1160 /*
1161  * ======== nodewrap_change_priority ========
1162  */
1163 u32 nodewrap_change_priority(union trapped_args *args, void *pr_ctxt)
1164 {
1165         u32 ret;
1166         struct node_res_object *node_res;
1167
1168         find_node_handle(&node_res, pr_ctxt,
1169                                 args->args_node_changepriority.hnode);
1170
1171         if (!node_res)
1172                 return -EFAULT;
1173
1174         ret = node_change_priority(node_res->hnode,
1175                                    args->args_node_changepriority.prio);
1176
1177         return ret;
1178 }
1179
1180 /*
1181  * ======== nodewrap_connect ========
1182  */
1183 u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt)
1184 {
1185         int status = 0;
1186         struct dsp_strmattr attrs;
1187         struct dsp_strmattr *pattrs = NULL;
1188         u32 cb_data_size;
1189         u32 __user *psize = (u32 __user *) args->args_node_connect.conn_param;
1190         u8 *pargs = NULL;
1191         struct node_res_object *node_res1, *node_res2;
1192         struct node_object *node1 = NULL, *node2 = NULL;
1193
1194         if ((int)args->args_node_connect.hnode != DSP_HGPPNODE) {
1195                 find_node_handle(&node_res1, pr_ctxt,
1196                                 args->args_node_connect.hnode);
1197                 if (node_res1)
1198                         node1 = node_res1->hnode;
1199         } else {
1200                 node1 = args->args_node_connect.hnode;
1201         }
1202
1203         if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) {
1204                 find_node_handle(&node_res2, pr_ctxt,
1205                                 args->args_node_connect.other_node);
1206                 if (node_res2)
1207                         node2 = node_res2->hnode;
1208         } else {
1209                 node2 = args->args_node_connect.other_node;
1210         }
1211
1212         if (!node1 || !node2)
1213                 return -EFAULT;
1214
1215         /* Optional argument */
1216         if (psize) {
1217                 if (get_user(cb_data_size, psize))
1218                         status = -EPERM;
1219
1220                 cb_data_size += sizeof(u32);
1221                 if (!status) {
1222                         pargs = kmalloc(cb_data_size, GFP_KERNEL);
1223                         if (pargs == NULL) {
1224                                 status = -ENOMEM;
1225                                 goto func_cont;
1226                         }
1227
1228                 }
1229                 CP_FM_USR(pargs, args->args_node_connect.conn_param, status,
1230                           cb_data_size);
1231                 if (status)
1232                         goto func_cont;
1233         }
1234         if (args->args_node_connect.pattrs) {   /* Optional argument */
1235                 CP_FM_USR(&attrs, args->args_node_connect.pattrs, status, 1);
1236                 if (!status)
1237                         pattrs = &attrs;
1238
1239         }
1240         if (!status) {
1241                 status = node_connect(node1,
1242                                       args->args_node_connect.stream_id,
1243                                       node2,
1244                                       args->args_node_connect.other_stream,
1245                                       pattrs, (struct dsp_cbdata *)pargs);
1246         }
1247 func_cont:
1248         kfree(pargs);
1249
1250         return status;
1251 }
1252
1253 /*
1254  * ======== nodewrap_create ========
1255  */
1256 u32 nodewrap_create(union trapped_args *args, void *pr_ctxt)
1257 {
1258         u32 ret;
1259         struct node_res_object *node_res;
1260
1261         find_node_handle(&node_res, pr_ctxt, args->args_node_create.hnode);
1262
1263         if (!node_res)
1264                 return -EFAULT;
1265
1266         ret = node_create(node_res->hnode);
1267
1268         return ret;
1269 }
1270
1271 /*
1272  * ======== nodewrap_delete ========
1273  */
1274 u32 nodewrap_delete(union trapped_args *args, void *pr_ctxt)
1275 {
1276         u32 ret;
1277         struct node_res_object *node_res;
1278
1279         find_node_handle(&node_res, pr_ctxt, args->args_node_delete.hnode);
1280
1281         if (!node_res)
1282                 return -EFAULT;
1283
1284         ret = node_delete(node_res, pr_ctxt);
1285
1286         return ret;
1287 }
1288
1289 /*
1290  *  ======== nodewrap_free_msg_buf ========
1291  */
1292 u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt)
1293 {
1294         int status = 0;
1295         struct dsp_bufferattr *pattr = NULL;
1296         struct dsp_bufferattr attr;
1297         struct node_res_object *node_res;
1298
1299         find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.hnode);
1300
1301         if (!node_res)
1302                 return -EFAULT;
1303
1304         if (args->args_node_freemsgbuf.pattr) { /* Optional argument */
1305                 CP_FM_USR(&attr, args->args_node_freemsgbuf.pattr, status, 1);
1306                 if (!status)
1307                         pattr = &attr;
1308
1309         }
1310
1311         if (!args->args_node_freemsgbuf.pbuffer)
1312                 return -EFAULT;
1313
1314         if (!status) {
1315                 status = node_free_msg_buf(node_res->hnode,
1316                                            args->args_node_freemsgbuf.pbuffer,
1317                                            pattr);
1318         }
1319
1320         return status;
1321 }
1322
1323 /*
1324  * ======== nodewrap_get_attr ========
1325  */
1326 u32 nodewrap_get_attr(union trapped_args *args, void *pr_ctxt)
1327 {
1328         int status = 0;
1329         struct dsp_nodeattr attr;
1330         struct node_res_object *node_res;
1331
1332         find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.hnode);
1333
1334         if (!node_res)
1335                 return -EFAULT;
1336
1337         status = node_get_attr(node_res->hnode, &attr,
1338                                args->args_node_getattr.attr_size);
1339         CP_TO_USR(args->args_node_getattr.pattr, &attr, status, 1);
1340
1341         return status;
1342 }
1343
1344 /*
1345  * ======== nodewrap_get_message ========
1346  */
1347 u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt)
1348 {
1349         int status;
1350         struct dsp_msg msg;
1351         struct node_res_object *node_res;
1352
1353         find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.hnode);
1354
1355         if (!node_res)
1356                 return -EFAULT;
1357
1358         status = node_get_message(node_res->hnode, &msg,
1359                                   args->args_node_getmessage.utimeout);
1360
1361         CP_TO_USR(args->args_node_getmessage.message, &msg, status, 1);
1362
1363         return status;
1364 }
1365
1366 /*
1367  * ======== nodewrap_pause ========
1368  */
1369 u32 nodewrap_pause(union trapped_args *args, void *pr_ctxt)
1370 {
1371         u32 ret;
1372         struct node_res_object *node_res;
1373
1374         find_node_handle(&node_res, pr_ctxt, args->args_node_pause.hnode);
1375
1376         if (!node_res)
1377                 return -EFAULT;
1378
1379         ret = node_pause(node_res->hnode);
1380
1381         return ret;
1382 }
1383
1384 /*
1385  * ======== nodewrap_put_message ========
1386  */
1387 u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt)
1388 {
1389         int status = 0;
1390         struct dsp_msg msg;
1391         struct node_res_object *node_res;
1392
1393         find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.hnode);
1394
1395         if (!node_res)
1396                 return -EFAULT;
1397
1398         CP_FM_USR(&msg, args->args_node_putmessage.message, status, 1);
1399
1400         if (!status) {
1401                 status =
1402                     node_put_message(node_res->hnode, &msg,
1403                                      args->args_node_putmessage.utimeout);
1404         }
1405
1406         return status;
1407 }
1408
1409 /*
1410  * ======== nodewrap_register_notify ========
1411  */
1412 u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt)
1413 {
1414         int status = 0;
1415         struct dsp_notification notification;
1416         struct node_res_object *node_res;
1417
1418         find_node_handle(&node_res, pr_ctxt,
1419                         args->args_node_registernotify.hnode);
1420
1421         if (!node_res)
1422                 return -EFAULT;
1423
1424         /* Initialize the notification data structure */
1425         notification.ps_name = NULL;
1426         notification.handle = NULL;
1427
1428         if (!args->args_proc_register_notify.event_mask)
1429                 CP_FM_USR(&notification,
1430                           args->args_proc_register_notify.hnotification,
1431                           status, 1);
1432
1433         status = node_register_notify(node_res->hnode,
1434                                       args->args_node_registernotify.event_mask,
1435                                       args->args_node_registernotify.
1436                                       notify_type, &notification);
1437         CP_TO_USR(args->args_node_registernotify.hnotification, &notification,
1438                   status, 1);
1439         return status;
1440 }
1441
1442 /*
1443  * ======== nodewrap_run ========
1444  */
1445 u32 nodewrap_run(union trapped_args *args, void *pr_ctxt)
1446 {
1447         u32 ret;
1448         struct node_res_object *node_res;
1449
1450         find_node_handle(&node_res, pr_ctxt, args->args_node_run.hnode);
1451
1452         if (!node_res)
1453                 return -EFAULT;
1454
1455         ret = node_run(node_res->hnode);
1456
1457         return ret;
1458 }
1459
1460 /*
1461  * ======== nodewrap_terminate ========
1462  */
1463 u32 nodewrap_terminate(union trapped_args *args, void *pr_ctxt)
1464 {
1465         int status;
1466         int tempstatus;
1467         struct node_res_object *node_res;
1468
1469         find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.hnode);
1470
1471         if (!node_res)
1472                 return -EFAULT;
1473
1474         status = node_terminate(node_res->hnode, &tempstatus);
1475
1476         CP_TO_USR(args->args_node_terminate.pstatus, &tempstatus, status, 1);
1477
1478         return status;
1479 }
1480
1481 /*
1482  * ======== nodewrap_get_uuid_props ========
1483  */
1484 u32 nodewrap_get_uuid_props(union trapped_args *args, void *pr_ctxt)
1485 {
1486         int status = 0;
1487         struct dsp_uuid node_uuid;
1488         struct dsp_ndbprops *pnode_props = NULL;
1489         void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
1490
1491         CP_FM_USR(&node_uuid, args->args_node_getuuidprops.node_id_ptr, status,
1492                   1);
1493         if (status)
1494                 goto func_cont;
1495         pnode_props = kmalloc(sizeof(struct dsp_ndbprops), GFP_KERNEL);
1496         if (pnode_props != NULL) {
1497                 status =
1498                     node_get_uuid_props(hprocessor, &node_uuid, pnode_props);
1499                 CP_TO_USR(args->args_node_getuuidprops.node_props, pnode_props,
1500                           status, 1);
1501         } else
1502                 status = -ENOMEM;
1503 func_cont:
1504         kfree(pnode_props);
1505         return status;
1506 }
1507
1508 /*
1509  * ======== find_strm_handle =========
1510  */
1511 inline void find_strm_handle(struct strm_res_object **strmres,
1512                                 void *pr_ctxt, void *hstream)
1513 {
1514         rcu_read_lock();
1515         *strmres = idr_find(((struct process_context *)pr_ctxt)->stream_id,
1516                                                         (int)hstream - 1);
1517         rcu_read_unlock();
1518         return;
1519 }
1520
1521 /*
1522  * ======== strmwrap_allocate_buffer ========
1523  */
1524 u32 strmwrap_allocate_buffer(union trapped_args *args, void *pr_ctxt)
1525 {
1526         int status;
1527         u8 **ap_buffer = NULL;
1528         u32 num_bufs = args->args_strm_allocatebuffer.num_bufs;
1529         struct strm_res_object *strm_res;
1530
1531         find_strm_handle(&strm_res, pr_ctxt,
1532                 args->args_strm_allocatebuffer.hstream);
1533
1534         if (!strm_res)
1535                 return -EFAULT;
1536
1537         if (num_bufs > MAX_BUFS)
1538                 return -EINVAL;
1539
1540         ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL);
1541         if (ap_buffer == NULL)
1542                 return -ENOMEM;
1543
1544         status = strm_allocate_buffer(strm_res,
1545                                       args->args_strm_allocatebuffer.usize,
1546                                       ap_buffer, num_bufs, pr_ctxt);
1547         if (!status) {
1548                 CP_TO_USR(args->args_strm_allocatebuffer.ap_buffer, ap_buffer,
1549                           status, num_bufs);
1550                 if (status) {
1551                         status = -EFAULT;
1552                         strm_free_buffer(strm_res,
1553                                          ap_buffer, num_bufs, pr_ctxt);
1554                 }
1555         }
1556         kfree(ap_buffer);
1557
1558         return status;
1559 }
1560
1561 /*
1562  * ======== strmwrap_close ========
1563  */
1564 u32 strmwrap_close(union trapped_args *args, void *pr_ctxt)
1565 {
1566         struct strm_res_object *strm_res;
1567
1568         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_close.hstream);
1569
1570         if (!strm_res)
1571                 return -EFAULT;
1572
1573         return strm_close(strm_res, pr_ctxt);
1574 }
1575
1576 /*
1577  * ======== strmwrap_free_buffer ========
1578  */
1579 u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt)
1580 {
1581         int status = 0;
1582         u8 **ap_buffer = NULL;
1583         u32 num_bufs = args->args_strm_freebuffer.num_bufs;
1584         struct strm_res_object *strm_res;
1585
1586         find_strm_handle(&strm_res, pr_ctxt,
1587                         args->args_strm_freebuffer.hstream);
1588
1589         if (!strm_res)
1590                 return -EFAULT;
1591
1592         if (num_bufs > MAX_BUFS)
1593                 return -EINVAL;
1594
1595         ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL);
1596         if (ap_buffer == NULL)
1597                 return -ENOMEM;
1598
1599         CP_FM_USR(ap_buffer, args->args_strm_freebuffer.ap_buffer, status,
1600                   num_bufs);
1601
1602         if (!status)
1603                 status = strm_free_buffer(strm_res,
1604                                           ap_buffer, num_bufs, pr_ctxt);
1605
1606         CP_TO_USR(args->args_strm_freebuffer.ap_buffer, ap_buffer, status,
1607                   num_bufs);
1608         kfree(ap_buffer);
1609
1610         return status;
1611 }
1612
1613 /*
1614  * ======== strmwrap_get_event_handle ========
1615  */
1616 u32 __deprecated strmwrap_get_event_handle(union trapped_args * args,
1617                                            void *pr_ctxt)
1618 {
1619         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1620         return -ENOSYS;
1621 }
1622
1623 /*
1624  * ======== strmwrap_get_info ========
1625  */
1626 u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt)
1627 {
1628         int status = 0;
1629         struct stream_info strm_info;
1630         struct dsp_streaminfo user;
1631         struct dsp_streaminfo *temp;
1632         struct strm_res_object *strm_res;
1633
1634         find_strm_handle(&strm_res, pr_ctxt,
1635                         args->args_strm_getinfo.hstream);
1636
1637         if (!strm_res)
1638                 return -EFAULT;
1639
1640         CP_FM_USR(&strm_info, args->args_strm_getinfo.stream_info, status, 1);
1641         temp = strm_info.user_strm;
1642
1643         strm_info.user_strm = &user;
1644
1645         if (!status) {
1646                 status = strm_get_info(strm_res->hstream,
1647                                        &strm_info,
1648                                        args->args_strm_getinfo.
1649                                        stream_info_size);
1650         }
1651         CP_TO_USR(temp, strm_info.user_strm, status, 1);
1652         strm_info.user_strm = temp;
1653         CP_TO_USR(args->args_strm_getinfo.stream_info, &strm_info, status, 1);
1654         return status;
1655 }
1656
1657 /*
1658  * ======== strmwrap_idle ========
1659  */
1660 u32 strmwrap_idle(union trapped_args *args, void *pr_ctxt)
1661 {
1662         u32 ret;
1663         struct strm_res_object *strm_res;
1664
1665         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_idle.hstream);
1666
1667         if (!strm_res)
1668                 return -EFAULT;
1669
1670         ret = strm_idle(strm_res->hstream, args->args_strm_idle.flush_flag);
1671
1672         return ret;
1673 }
1674
1675 /*
1676  * ======== strmwrap_issue ========
1677  */
1678 u32 strmwrap_issue(union trapped_args *args, void *pr_ctxt)
1679 {
1680         int status = 0;
1681         struct strm_res_object *strm_res;
1682
1683         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_issue.hstream);
1684
1685         if (!strm_res)
1686                 return -EFAULT;
1687
1688         if (!args->args_strm_issue.pbuffer)
1689                 return -EFAULT;
1690
1691         /* No need of doing CP_FM_USR for the user buffer (pbuffer)
1692            as this is done in Bridge internal function bridge_chnl_add_io_req
1693            in chnl_sm.c */
1694         status = strm_issue(strm_res->hstream,
1695                             args->args_strm_issue.pbuffer,
1696                             args->args_strm_issue.dw_bytes,
1697                             args->args_strm_issue.dw_buf_size,
1698                             args->args_strm_issue.dw_arg);
1699
1700         return status;
1701 }
1702
1703 /*
1704  * ======== strmwrap_open ========
1705  */
1706 u32 strmwrap_open(union trapped_args *args, void *pr_ctxt)
1707 {
1708         int status = 0;
1709         struct strm_attr attr;
1710         struct strm_res_object *strm_res_obj;
1711         struct dsp_streamattrin strm_attr_in;
1712         struct node_res_object *node_res;
1713         int strmid;
1714
1715         find_node_handle(&node_res, pr_ctxt, args->args_strm_open.hnode);
1716
1717         if (!node_res)
1718                 return -EFAULT;
1719
1720         CP_FM_USR(&attr, args->args_strm_open.attr_in, status, 1);
1721
1722         if (attr.stream_attr_in != NULL) {      /* Optional argument */
1723                 CP_FM_USR(&strm_attr_in, attr.stream_attr_in, status, 1);
1724                 if (!status) {
1725                         attr.stream_attr_in = &strm_attr_in;
1726                         if (attr.stream_attr_in->strm_mode == STRMMODE_LDMA)
1727                                 return -ENOSYS;
1728                 }
1729
1730         }
1731         status = strm_open(node_res->hnode,
1732                            args->args_strm_open.direction,
1733                            args->args_strm_open.index, &attr, &strm_res_obj,
1734                            pr_ctxt);
1735         if (!status) {
1736                 strmid = strm_res_obj->id + 1;
1737                 CP_TO_USR(args->args_strm_open.ph_stream, &strmid, status, 1);
1738         }
1739         return status;
1740 }
1741
1742 /*
1743  * ======== strmwrap_reclaim ========
1744  */
1745 u32 strmwrap_reclaim(union trapped_args *args, void *pr_ctxt)
1746 {
1747         int status = 0;
1748         u8 *buf_ptr;
1749         u32 ul_bytes;
1750         u32 dw_arg;
1751         u32 ul_buf_size;
1752         struct strm_res_object *strm_res;
1753
1754         find_strm_handle(&strm_res, pr_ctxt, args->args_strm_reclaim.hstream);
1755
1756         if (!strm_res)
1757                 return -EFAULT;
1758
1759         status = strm_reclaim(strm_res->hstream, &buf_ptr,
1760                               &ul_bytes, &ul_buf_size, &dw_arg);
1761         CP_TO_USR(args->args_strm_reclaim.buf_ptr, &buf_ptr, status, 1);
1762         CP_TO_USR(args->args_strm_reclaim.bytes, &ul_bytes, status, 1);
1763         CP_TO_USR(args->args_strm_reclaim.pdw_arg, &dw_arg, status, 1);
1764
1765         if (args->args_strm_reclaim.buf_size_ptr != NULL) {
1766                 CP_TO_USR(args->args_strm_reclaim.buf_size_ptr, &ul_buf_size,
1767                           status, 1);
1768         }
1769
1770         return status;
1771 }
1772
1773 /*
1774  * ======== strmwrap_register_notify ========
1775  */
1776 u32 strmwrap_register_notify(union trapped_args *args, void *pr_ctxt)
1777 {
1778         int status = 0;
1779         struct dsp_notification notification;
1780         struct strm_res_object *strm_res;
1781
1782         find_strm_handle(&strm_res, pr_ctxt,
1783                         args->args_strm_registernotify.hstream);
1784
1785         if (!strm_res)
1786                 return -EFAULT;
1787
1788         /* Initialize the notification data structure */
1789         notification.ps_name = NULL;
1790         notification.handle = NULL;
1791
1792         status = strm_register_notify(strm_res->hstream,
1793                                       args->args_strm_registernotify.event_mask,
1794                                       args->args_strm_registernotify.
1795                                       notify_type, &notification);
1796         CP_TO_USR(args->args_strm_registernotify.hnotification, &notification,
1797                   status, 1);
1798
1799         return status;
1800 }
1801
1802 /*
1803  * ======== strmwrap_select ========
1804  */
1805 u32 strmwrap_select(union trapped_args *args, void *pr_ctxt)
1806 {
1807         u32 mask;
1808         struct strm_object *strm_tab[MAX_STREAMS];
1809         int status = 0;
1810         struct strm_res_object *strm_res;
1811         int *ids[MAX_STREAMS];
1812         int i;
1813
1814         if (args->args_strm_select.strm_num > MAX_STREAMS)
1815                 return -EINVAL;
1816
1817         CP_FM_USR(ids, args->args_strm_select.stream_tab, status,
1818                 args->args_strm_select.strm_num);
1819
1820         if (status)
1821                 return status;
1822
1823         for (i = 0; i < args->args_strm_select.strm_num; i++) {
1824                 find_strm_handle(&strm_res, pr_ctxt, ids[i]);
1825
1826                 if (!strm_res)
1827                         return -EFAULT;
1828
1829                 strm_tab[i] = strm_res->hstream;
1830         }
1831
1832         if (!status) {
1833                 status = strm_select(strm_tab, args->args_strm_select.strm_num,
1834                                      &mask, args->args_strm_select.utimeout);
1835         }
1836         CP_TO_USR(args->args_strm_select.pmask, &mask, status, 1);
1837         return status;
1838 }
1839
1840 /* CMM */
1841
1842 /*
1843  * ======== cmmwrap_calloc_buf ========
1844  */
1845 u32 __deprecated cmmwrap_calloc_buf(union trapped_args * args, void *pr_ctxt)
1846 {
1847         /* This operation is done in kernel */
1848         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1849         return -ENOSYS;
1850 }
1851
1852 /*
1853  * ======== cmmwrap_free_buf ========
1854  */
1855 u32 __deprecated cmmwrap_free_buf(union trapped_args * args, void *pr_ctxt)
1856 {
1857         /* This operation is done in kernel */
1858         pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1859         return -ENOSYS;
1860 }
1861
1862 /*
1863  * ======== cmmwrap_get_handle ========
1864  */
1865 u32 cmmwrap_get_handle(union trapped_args *args, void *pr_ctxt)
1866 {
1867         int status = 0;
1868         struct cmm_object *hcmm_mgr;
1869         void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
1870
1871         status = cmm_get_handle(hprocessor, &hcmm_mgr);
1872
1873         CP_TO_USR(args->args_cmm_gethandle.ph_cmm_mgr, &hcmm_mgr, status, 1);
1874
1875         return status;
1876 }
1877
1878 /*
1879  * ======== cmmwrap_get_info ========
1880  */
1881 u32 cmmwrap_get_info(union trapped_args *args, void *pr_ctxt)
1882 {
1883         int status = 0;
1884         struct cmm_info cmm_info_obj;
1885
1886         status = cmm_get_info(args->args_cmm_getinfo.hcmm_mgr, &cmm_info_obj);
1887
1888         CP_TO_USR(args->args_cmm_getinfo.cmm_info_obj, &cmm_info_obj, status,
1889                   1);
1890
1891         return status;
1892 }