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