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