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