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