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