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 
_cp_fm_usr(void * to,const void __user * from,int * err,unsigned long bytes)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 
_cp_to_usr(void __user * to,const void * from,int * err,unsigned long bytes)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  */
api_call_dev_ioctl(u32 cmd,union trapped_args * args,u32 * result,void * pr_ctxt)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  */
api_exit(void)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  */
api_init(void)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  */
api_init_complete2(void)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  */
mgrwrap_enum_node_info(union trapped_args * args,void * pr_ctxt)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  */
mgrwrap_enum_proc_info(union trapped_args * args,void * pr_ctxt)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  */
mgrwrap_register_object(union trapped_args * args,void * pr_ctxt)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  */
mgrwrap_unregister_object(union trapped_args * args,void * pr_ctxt)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  */
mgrwrap_wait_for_bridge_events(union trapped_args * args,void * pr_ctxt)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  */
mgrwrap_get_process_resources_info(union trapped_args * args,void * pr_ctxt)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  */
procwrap_attach(union trapped_args * args,void * pr_ctxt)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  */
procwrap_ctrl(union trapped_args * args,void * pr_ctxt)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  */
procwrap_detach(union trapped_args * args,void * pr_ctxt)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  */
procwrap_enum_node_info(union trapped_args * args,void * pr_ctxt)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 
procwrap_end_dma(union trapped_args * args,void * pr_ctxt)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 
procwrap_begin_dma(union trapped_args * args,void * pr_ctxt)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  */
procwrap_flush_memory(union trapped_args * args,void * pr_ctxt)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  */
procwrap_invalidate_memory(union trapped_args * args,void * pr_ctxt)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  */
procwrap_enum_resources(union trapped_args * args,void * pr_ctxt)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  */
procwrap_get_state(union trapped_args * args,void * pr_ctxt)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  */
procwrap_get_trace(union trapped_args * args,void * pr_ctxt)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  */
procwrap_load(union trapped_args * args,void * pr_ctxt)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  */
procwrap_map(union trapped_args * args,void * pr_ctxt)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  */
procwrap_register_notify(union trapped_args * args,void * pr_ctxt)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  */
procwrap_reserve_memory(union trapped_args * args,void * pr_ctxt)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  */
procwrap_start(union trapped_args * args,void * pr_ctxt)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  */
procwrap_un_map(union trapped_args * args,void * pr_ctxt)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  */
procwrap_un_reserve_memory(union trapped_args * args,void * pr_ctxt)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  */
procwrap_stop(union trapped_args * args,void * pr_ctxt)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  */
find_node_handle(struct node_res_object ** noderes,void * pr_ctxt,void * hnode)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  */
nodewrap_allocate(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_alloc_msg_buf(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_change_priority(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_connect(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_create(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_delete(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_free_msg_buf(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_get_attr(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_get_message(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_pause(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_put_message(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_register_notify(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_run(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_terminate(union trapped_args * args,void * pr_ctxt)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  */
nodewrap_get_uuid_props(union trapped_args * args,void * pr_ctxt)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  */
find_strm_handle(struct strm_res_object ** strmres,void * pr_ctxt,void * hstream)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  */
strmwrap_allocate_buffer(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_close(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_free_buffer(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_get_event_handle(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_get_info(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_idle(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_issue(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_open(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_reclaim(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_register_notify(union trapped_args * args,void * pr_ctxt)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  */
strmwrap_select(union trapped_args * args,void * pr_ctxt)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  */
cmmwrap_calloc_buf(union trapped_args * args,void * pr_ctxt)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  */
cmmwrap_free_buf(union trapped_args * args,void * pr_ctxt)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  */
cmmwrap_get_handle(union trapped_args * args,void * pr_ctxt)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  */
cmmwrap_get_info(union trapped_args * args,void * pr_ctxt)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 }
1841