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