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