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