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