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