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