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